1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#!/usr/bin/python
2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Copyright (c) 2009 Google Inc. All rights reserved.
4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Redistribution and use in source and binary forms, with or without
6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# modification, are permitted provided that the following conditions are
7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# met:
8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#    * Redistributions of source code must retain the above copyright
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# notice, this list of conditions and the following disclaimer.
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#    * Redistributions in binary form must reproduce the above
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# copyright notice, this list of conditions and the following disclaimer
13ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# in the documentation and/or other materials provided with the
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# distribution.
15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#    * Neither the name of Google Inc. nor the names of its
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# contributors may be used to endorse or promote products derived from
17ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# this software without specific prior written permission.
18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
31ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang"""Does google-lint on c++ files.
32ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
33ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangThe goal of this script is to identify places in the code that *may*
34ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangbe in non-compliance with google style.  It does not attempt to fix
35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangup these problems -- the point is to educate.  It does also not
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangattempt to find all problems, or to ensure that everything it does
37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangfind is legitimately a problem.
38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangIn particular, we can get very confused by /* and // inside strings!
40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangWe do a small hack, which is to ignore //'s with "'s after them on the
41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangsame line, but it is far from perfect (in either direction).
42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang"""
43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport codecs
45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport copy
46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport getopt
47ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport math  # for log
48ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport os
49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport re
50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport sre_compile
51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport string
52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport sys
53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangimport unicodedata
54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
55ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_USAGE = """
57ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangSyntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
58b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   [--counting=total|toplevel|detailed] [--root=subdir]
59b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   [--linelength=digits]
60ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        <file> [file] ...
61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  The style guidelines this tries to follow are those in
63ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
65ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Every problem is given a confidence score from 1-5, with 5 meaning we are
66ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  certain of the problem, and 1 meaning it could be a legitimate construct.
67ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  This will miss some errors, and is not a substitute for a code review.
68ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  To suppress false-positive errors of a certain category, add a
70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)
71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  suppresses errors of all categories on that line.
72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
73ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  The files passed in will be linted; at least one file must be provided.
74b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Default linted extensions are .cc, .cpp, .cu, .cuh and .h.  Change the
75b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  extensions with the --extensions flag.
76ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
77ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Flags:
78ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    output=vs7
80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      By default, the output is formatted to ease emacs parsing.  Visual Studio
81ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      compatible output (vs7) may also be used.  Other formats are unsupported.
82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
83ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    verbose=#
84ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Specify a number 0-5 to restrict errors to certain verbosity levels.
85ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
86ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filter=-x,+y,...
87ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Specify a comma-separated list of category-filters to apply: only
88ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error messages whose category names pass the filters will be printed.
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      (Category names are printed with the message and look like
90ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      "[whitespace/indent]".)  Filters are evaluated left to right.
91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      "-FOO" and "FOO" means "do not print categories that start with FOO".
92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      "+FOO" means "do print categories that start with FOO".
93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Examples: --filter=-whitespace,+whitespace/braces
95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                --filter=whitespace,runtime/printf,+runtime/printf_format
96ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                --filter=-,+build/include_what_you_use
97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      To see a list of all the categories used in cpplint, pass no arg:
99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         --filter=
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    counting=total|toplevel|detailed
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      The total number of errors found is always printed. If
103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      'toplevel' is provided, then the count of errors in each of
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      the top-level categories like 'build' and 'whitespace' will
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      also be printed. If 'detailed' is provided, then a count
106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      is provided for each category like 'build/class'.
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    root=subdir
109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      The root directory used for deriving header guard CPP variable.
110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      By default, the header guard CPP variable is calculated as the relative
111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      path to the directory that contains .git, .hg, or .svn.  When this flag
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      is specified, the relative path is calculated from the specified
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      directory. If the specified directory does not exist, this flag is
114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ignored.
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Examples:
117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        Assuing that src/.git exists, the header guard CPP variables for
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        src/chrome/browser/ui/browser.h are:
119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        No flag => CHROME_BROWSER_UI_BROWSER_H_
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        --root=chrome => BROWSER_UI_BROWSER_H_
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        --root=chrome/browser => UI_BROWSER_H_
123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
124b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    linelength=digits
125b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      This is the allowed line length for the project. The default value is
126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      80 characters.
127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
128b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      Examples:
129b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        --linelength=120
130b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
131b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    extensions=extension,extension,...
132b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      The allowed file extensions that cpplint will check
133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
134b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      Examples:
135b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        --extensions=hpp,cpp
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang"""
137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# We categorize each error message we print.  Here are the categories.
139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# We want an explicit list so we can list them all in cpplint --filter=.
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# If you add a new error message with a new category, add it to the list
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# here!  cpplint_unittest.py should tell you if you forget to do this.
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_ERROR_CATEGORIES = [
143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/class',
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/deprecated',
145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/endif_comment',
146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/explicit_make_pair',
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/forward_decl',
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/header_guard',
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/include',
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/include_alpha',
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/include_order',
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/include_what_you_use',
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/namespaces',
154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/printf_format',
155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'build/storage_class',
156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'legal/copyright',
157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/alt_tokens',
158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/braces',
159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/casting',
160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/check',
161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/constructors',
162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/fn_size',
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/function',
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/multiline_comment',
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/multiline_string',
166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/namespace',
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/nolint',
168b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  'readability/nul',
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/streams',
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/todo',
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'readability/utf8',
172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/arrays',
173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/casting',
174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/explicit',
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/int',
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/init',
177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/invalid_increment',
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/member_string_references',
179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/memset',
180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/operator',
181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/printf',
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/printf_format',
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/references',
184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/sizeof',
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/string',
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'runtime/threadsafe_fn',
187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  'runtime/vlog',
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/blank_line',
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/braces',
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/comma',
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/comments',
192b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  'whitespace/empty_conditional_body',
193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/empty_loop_body',
194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/end_of_line',
195ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/ending_newline',
196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/forcolon',
197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/indent',
198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/line_length',
199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/newline',
200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/operators',
201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/parens',
202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/semicolon',
203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/tab',
204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'whitespace/todo'
205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ]
206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# The default state of the category filter. This is overrided by the --filter=
208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# flag. By default all errors are on, so only add here categories that should be
209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# off by default (i.e., categories that must be enabled by the --filter= flags).
210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# All entries here should start with a '-' or '+', as in the --filter= flag.
211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_DEFAULT_FILTERS = ['-build/include_alpha']
212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# We used to check for high-bit characters, but after much discussion we
214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# decided those were OK, as long as they were in UTF-8 and didn't represent
215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# hard-coded international strings, which belong in a separate i18n file.
216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# C++ headers
219ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_CPP_HEADERS = frozenset([
220b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Legacy
221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'algobase.h',
222b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'algo.h',
223b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'alloc.h',
224b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'builtinbuf.h',
225b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'bvector.h',
226b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'complex.h',
227b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'defalloc.h',
228b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'deque.h',
229b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'editbuf.h',
230b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'fstream.h',
231b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'function.h',
232b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'hash_map',
233b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'hash_map.h',
234b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'hash_set',
235b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'hash_set.h',
236b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'hashtable.h',
237b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'heap.h',
238b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'indstream.h',
239b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iomanip.h',
240b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iostream.h',
241b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'istream.h',
242b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iterator.h',
243b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'list.h',
244b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'map.h',
245b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'multimap.h',
246b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'multiset.h',
247b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ostream.h',
248b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'pair.h',
249b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'parsestream.h',
250b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'pfstream.h',
251b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'procbuf.h',
252b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'pthread_alloc',
253b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'pthread_alloc.h',
254b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'rope',
255b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'rope.h',
256b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ropeimpl.h',
257b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'set.h',
258b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'slist',
259b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'slist.h',
260b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stack.h',
261b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stdiostream.h',
262b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stl_alloc.h',
263b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stl_relops.h',
264b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'streambuf.h',
265b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stream.h',
266b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'strfile.h',
267b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'strstream.h',
268b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'tempbuf.h',
269b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'tree.h',
270b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'type_traits.h',
271b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'vector.h',
272b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # 17.6.1.2 C++ library headers
273b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'algorithm',
274b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'array',
275b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'atomic',
276b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'bitset',
277b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'chrono',
278b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'codecvt',
279b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'complex',
280b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'condition_variable',
281b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'deque',
282b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'exception',
283b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'forward_list',
284b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'fstream',
285b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'functional',
286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'future',
287b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'initializer_list',
288b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iomanip',
289b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ios',
290b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iosfwd',
291b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iostream',
292b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'istream',
293b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'iterator',
294b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'limits',
295b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'list',
296b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'locale',
297b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'map',
298b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'memory',
299b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'mutex',
300b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'new',
301b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'numeric',
302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ostream',
303b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'queue',
304b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'random',
305b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ratio',
306b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'regex',
307b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'set',
308b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'sstream',
309b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stack',
310b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'stdexcept',
311b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'streambuf',
312b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'string',
313b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'strstream',
314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'system_error',
315b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'thread',
316b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'tuple',
317b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'typeindex',
318b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'typeinfo',
319b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'type_traits',
320b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'unordered_map',
321b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'unordered_set',
322b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'utility',
323b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'valarray',
324b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'vector',
325b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # 17.6.1.2 C++ headers for C library facilities
326b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cassert',
327b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ccomplex',
328b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cctype',
329b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cerrno',
330b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cfenv',
331b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cfloat',
332b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cinttypes',
333b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ciso646',
334b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'climits',
335b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'clocale',
336b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cmath',
337b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'csetjmp',
338b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'csignal',
339b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdalign',
340b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdarg',
341b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdbool',
342b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstddef',
343b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdint',
344b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdio',
345b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstdlib',
346b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cstring',
347b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ctgmath',
348b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'ctime',
349b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cuchar',
350b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cwchar',
351b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    'cwctype',
352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ])
353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
354ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Assertion macros.  These are defined in base/logging.h and
355ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# testing/base/gunit.h.  Note that the _M versions need to come first
356ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# for substring matching to work.
357ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_CHECK_MACROS = [
358ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'DCHECK', 'CHECK',
359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'EXPECT_TRUE_M', 'EXPECT_TRUE',
360ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'ASSERT_TRUE_M', 'ASSERT_TRUE',
361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'EXPECT_FALSE_M', 'EXPECT_FALSE',
362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'ASSERT_FALSE_M', 'ASSERT_FALSE',
363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ]
364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
366ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
367ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
368ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangfor op, replacement in [('==', 'EQ'), ('!=', 'NE'),
369ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                        ('>=', 'GE'), ('>', 'GT'),
370ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                        ('<=', 'LE'), ('<', 'LT')]:
371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangfor op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            ('>=', 'LT'), ('>', 'LE'),
380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            ('<=', 'GT'), ('<', 'GE')]:
381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Alternative tokens and their replacements.  For full list, see section 2.5
387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Alternative tokens [lex.digraph] in the C++ standard.
388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Digraphs (such as '%:') are not included here since it's a mess to
390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# match those on a word boundary.
391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_ALT_TOKEN_REPLACEMENT = {
392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'and': '&&',
393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'bitor': '|',
394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'or': '||',
395ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'xor': '^',
396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'compl': '~',
397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'bitand': '&',
398ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'and_eq': '&=',
399ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'or_eq': '|=',
400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'xor_eq': '^=',
401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'not': '!',
402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'not_eq': '!='
403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Compile regular expression that matches all the above keywords.  The "[ =()]"
406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# bit is meant to avoid matching these keywords outside of boolean expressions.
407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#
408b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# False positives include C-style multi-line comments and multi-line strings
409b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# but those have always been troublesome for cpplint.
410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# These constants define types of headers for use with
415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# _IncludeState.CheckNextIncludeOrder().
416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_C_SYS_HEADER = 1
417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_CPP_SYS_HEADER = 2
418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_LIKELY_MY_HEADER = 3
419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_POSSIBLE_MY_HEADER = 4
420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_OTHER_HEADER = 5
421ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# These constants define the current inline assembly state
423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_NO_ASM = 0       # Outside of inline assembly block
424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_INSIDE_ASM = 1   # Inside inline assembly block
425ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_END_ASM = 2      # Last line of inline assembly block
426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_BLOCK_ASM = 3    # The whole block is an inline assembly block
427ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Match start of assembly blocks
429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                        r'(?:\s+(volatile|__volatile__))?'
431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                        r'\s*[{(]')
432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_regexp_compile_cache = {}
435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Finds occurrences of NOLINT or NOLINT(...).
437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?')
438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# {str, set(int)}: a map from error categories to sets of linenumbers
440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# on which those errors are expected and should be suppressed.
441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_error_suppressions = {}
442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# The root directory used for deriving header guard CPP variable.
444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# This is set by --root flag.
445ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_root = None
446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
447b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# The allowed line length of files.
448b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# This is set by --linelength flag.
449b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_line_length = 80
450b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
451b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# The allowed extensions for file names
452b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# This is set by --extensions flag.
453b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
454b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ParseNolintSuppressions(filename, raw_line, linenum, error):
456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Updates the global list of error-suppressions.
457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Parses any NOLINT comments on the current line, updating the global
459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  error_suppressions store.  Reports an error if the NOLINT comment
460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  was malformed.
461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: str, the name of the input file.
464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    raw_line: str, the line of input text, with comments.
465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: int, the number of the current line.
466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: function, an error handler.
467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*).
469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  matched = _RE_SUPPRESSION.search(raw_line)
470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if matched:
471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    category = matched.group(1)
472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if category in (None, '(*)'):  # => "suppress all"
473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _error_suppressions.setdefault(None, set()).add(linenum)
474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if category.startswith('(') and category.endswith(')'):
476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        category = category[1:-1]
477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if category in _ERROR_CATEGORIES:
478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          _error_suppressions.setdefault(category, set()).add(linenum)
479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          error(filename, linenum, 'readability/nolint', 5,
481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                'Unknown NOLINT error category: %s' % category)
482ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ResetNolintSuppressions():
485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  "Resets the set of NOLINT suppressions to empty."
486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _error_suppressions.clear()
487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef IsErrorSuppressedByNolint(category, linenum):
490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Returns true if the specified error category is suppressed on this line.
491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Consults the global error_suppressions map populated by
493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ParseNolintSuppressions/ResetNolintSuppressions.
494ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    category: str, the category of the error.
497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: int, the current line number.
498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    bool, True iff the error should be suppressed due to a NOLINT comment.
500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return (linenum in _error_suppressions.get(category, set()) or
502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          linenum in _error_suppressions.get(None, set()))
503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef Match(pattern, s):
505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Matches the string with the pattern, caching the compiled regexp."""
506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The regexp compilation caching is inlined in both Match and Search for
507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # performance reasons; factoring it out into a separate function turns out
508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # to be noticeably expensive.
509b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if pattern not in _regexp_compile_cache:
510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _regexp_compile_cache[pattern].match(s)
512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
514b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef ReplaceAll(pattern, rep, s):
515b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Replaces instances of pattern in a string with a replacement.
516b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
517b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  The compiled regex is kept in a cache shared by Match and Search.
518b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
519b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
520b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    pattern: regex pattern
521b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    rep: replacement text
522b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    s: search string
523b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
524b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Returns:
525b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    string with replacements made (or original string if no replacements)
526b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
527b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if pattern not in _regexp_compile_cache:
528b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
529b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return _regexp_compile_cache[pattern].sub(rep, s)
530b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
531b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef Search(pattern, s):
533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Searches the string for the pattern, caching the compiled regexp."""
534b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if pattern not in _regexp_compile_cache:
535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _regexp_compile_cache[pattern].search(s)
537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _IncludeState(dict):
540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Tracks line numbers for includes, and the order in which includes appear.
541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  As a dict, an _IncludeState object serves as a mapping between include
543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename and line number on which that file was included.
544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Call CheckNextIncludeOrder() once for each header in the file, passing
546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  in the type constants defined above. Calls in an illegal order will
547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  raise an _IncludeError with an appropriate error message.
548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
550ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # self._section will move monotonically through this set. If it ever
551ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # needs to move backwards, CheckNextIncludeOrder will raise an error.
552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _INITIAL_SECTION = 0
553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _MY_H_SECTION = 1
554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _C_SECTION = 2
555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _CPP_SECTION = 3
556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _OTHER_H_SECTION = 4
557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _TYPE_NAMES = {
559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _C_SYS_HEADER: 'C system header',
560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _CPP_SYS_HEADER: 'C++ system header',
561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _LIKELY_MY_HEADER: 'header this file implements',
562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _POSSIBLE_MY_HEADER: 'header this file may implement',
563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _OTHER_HEADER: 'other header',
564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SECTION_NAMES = {
566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _INITIAL_SECTION: "... nothing. (This can't be an error.)",
567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _MY_H_SECTION: 'a header this file implements',
568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _C_SECTION: 'C system header',
569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _CPP_SECTION: 'C++ system header',
570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _OTHER_H_SECTION: 'other header',
571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self):
574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    dict.__init__(self)
575b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    self.ResetSection()
576b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
577b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  def ResetSection(self):
578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # The name of the current section.
579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self._section = self._INITIAL_SECTION
580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # The path of last found header.
581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self._last_header = ''
582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
583b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  def SetLastHeader(self, header_path):
584b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    self._last_header = header_path
585b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CanonicalizeAlphabeticalOrder(self, header_path):
587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Returns a path canonicalized for alphabetical comparison.
588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    - replaces "-" with "_" so they both cmp the same.
590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    - removes '-inl' since we don't require them to be after the main header.
591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    - lowercase everything, just in case.
592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      header_path: Path to be canonicalized.
595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Canonicalized path.
598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
601b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Check if a header is in alphabetical order with the previous header.
603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
605b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      clean_lines: A CleansedLines instance containing the file.
606b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      linenum: The number of the line to check.
607b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      header_path: Canonicalized header to be checked.
608ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Returns true if the header is in alphabetical order.
611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
612b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # If previous section is different from current section, _last_header will
613b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # be reset to empty string, so it's always less than current header.
614b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
615b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # If previous line was a blank line, assume that the headers are
616b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # intentionally sorted the way they are.
617b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (self._last_header > header_path and
618b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        not Match(r'^\s*$', clean_lines.elided[linenum - 1])):
619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return False
620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return True
621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CheckNextIncludeOrder(self, header_type):
623ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Returns a non-empty error message if the next header is out of order.
624ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
625ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    This function also updates the internal state to be ready to check
626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    the next include.
627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
628ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
629ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      header_type: One of the _XXX_HEADER constants defined above.
630ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
631ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      The empty string if the header is in the right order, or an
633ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error message describing what's wrong.
634ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
635ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error_message = ('Found %s after %s' %
637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     (self._TYPE_NAMES[header_type],
638ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      self._SECTION_NAMES[self._section]))
639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    last_section = self._section
641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
642ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if header_type == _C_SYS_HEADER:
643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self._section <= self._C_SECTION:
644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._C_SECTION
645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._last_header = ''
647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return error_message
648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif header_type == _CPP_SYS_HEADER:
649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self._section <= self._CPP_SECTION:
650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._CPP_SECTION
651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._last_header = ''
653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return error_message
654ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif header_type == _LIKELY_MY_HEADER:
655ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self._section <= self._MY_H_SECTION:
656ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._MY_H_SECTION
657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._OTHER_H_SECTION
659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif header_type == _POSSIBLE_MY_HEADER:
660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self._section <= self._MY_H_SECTION:
661ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._MY_H_SECTION
662ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # This will always be the fallback because we're not sure
664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # enough that the header is associated with this file.
665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self._section = self._OTHER_H_SECTION
666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      assert header_type == _OTHER_HEADER
668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self._section = self._OTHER_H_SECTION
669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if last_section != self._section:
671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self._last_header = ''
672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return ''
674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _CppLintState(object):
677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Maintains module-wide state.."""
678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self):
680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.verbose_level = 1  # global setting.
681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.error_count = 0    # global count of reported errors
682ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # filters to apply when emitting error messages
683ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.filters = _DEFAULT_FILTERS[:]
684ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.counting = 'total'  # In what way are we counting errors?
685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.errors_by_category = {}  # string to int dict storing error counts
686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # output format:
688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # "emacs" - format that emacs can parse (default)
689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # "vs7" - format that Microsoft Visual Studio 7 can parse
690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.output_format = 'emacs'
691ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def SetOutputFormat(self, output_format):
693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Sets the output format for errors."""
694ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.output_format = output_format
695ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
696ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def SetVerboseLevel(self, level):
697ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Sets the module's verbosity, and returns the previous setting."""
698ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    last_verbose_level = self.verbose_level
699ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.verbose_level = level
700ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return last_verbose_level
701ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
702ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def SetCountingStyle(self, counting_style):
703ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Sets the module's counting options."""
704ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.counting = counting_style
705ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
706ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def SetFilters(self, filters):
707ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Sets the error-message filters.
708ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
709ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    These filters are applied when deciding whether to emit a given
710ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error message.
711ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
712ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
713ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filters: A string of comma-separated filters (eg "+whitespace/indent").
714ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               Each filter should start with + or -; else we die.
715ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
716ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Raises:
717ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ValueError: The comma-separated filters did not all start with '+' or '-'.
718ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
719ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
720ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Default filters always have less priority than the flag ones.
721ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.filters = _DEFAULT_FILTERS[:]
722ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for filt in filters.split(','):
723ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      clean_filt = filt.strip()
724ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if clean_filt:
725ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self.filters.append(clean_filt)
726ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for filt in self.filters:
727ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not (filt.startswith('+') or filt.startswith('-')):
728ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        raise ValueError('Every filter in --filters must start with + or -'
729ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                         ' (%s does not)' % filt)
730ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
731ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def ResetErrorCounts(self):
732ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Sets the module's error statistic back to zero."""
733ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.error_count = 0
734ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.errors_by_category = {}
735ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
736ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def IncrementErrorCount(self, category):
737ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Bumps the module's error statistic."""
738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.error_count += 1
739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.counting in ('toplevel', 'detailed'):
740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self.counting != 'detailed':
741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        category = category.split('/')[0]
742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if category not in self.errors_by_category:
743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self.errors_by_category[category] = 0
744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.errors_by_category[category] += 1
745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def PrintErrorCounts(self):
747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Print a summary of errors by category, and the total."""
748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for category, count in self.errors_by_category.iteritems():
749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      sys.stderr.write('Category \'%s\' errors found: %d\n' %
750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                       (category, count))
751ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    sys.stderr.write('Total errors found: %d\n' % self.error_count)
752ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
753ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_cpplint_state = _CppLintState()
754ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _OutputFormat():
757ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Gets the module's output format."""
758ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _cpplint_state.output_format
759ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
760ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
761ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _SetOutputFormat(output_format):
762ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Sets the module's output format."""
763ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _cpplint_state.SetOutputFormat(output_format)
764ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
765ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
766ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _VerboseLevel():
767ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Returns the module's verbosity setting."""
768ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _cpplint_state.verbose_level
769ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
770ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
771ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _SetVerboseLevel(level):
772ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Sets the module's verbosity, and returns the previous setting."""
773ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _cpplint_state.SetVerboseLevel(level)
774ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
775ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
776ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _SetCountingStyle(level):
777ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Sets the module's counting options."""
778ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _cpplint_state.SetCountingStyle(level)
779ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
780ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
781ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _Filters():
782ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Returns the module's list of output filters, as a list."""
783ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _cpplint_state.filters
784ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
785ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
786ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _SetFilters(filters):
787ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Sets the module's error-message filters.
788ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
789ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  These filters are applied when deciding whether to emit a given
790ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  error message.
791ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
792ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
793ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filters: A string of comma-separated filters (eg "whitespace/indent").
794ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             Each filter should start with + or -; else we die.
795ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
796ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _cpplint_state.SetFilters(filters)
797ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
798ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
799ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _FunctionState(object):
800ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Tracks current function name and the number of lines in its body."""
801ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
802ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _NORMAL_TRIGGER = 250  # for --v=0, 500 for --v=1, etc.
803ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _TEST_TRIGGER = 400    # about 50% more than _NORMAL_TRIGGER.
804ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
805ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self):
806ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.in_a_function = False
807ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.lines_in_function = 0
808ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.current_function = ''
809ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
810ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Begin(self, function_name):
811ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Start analyzing function body.
812ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
813ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
814ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      function_name: The name of the function being tracked.
815ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
816ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.in_a_function = True
817ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.lines_in_function = 0
818ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.current_function = function_name
819ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
820ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Count(self):
821ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Count line in current function body."""
822ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.in_a_function:
823ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.lines_in_function += 1
824ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
825ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Check(self, error, filename, linenum):
826ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Report if too many lines in function body.
827ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
828ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
829ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error: The function to call with any errors found.
830ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename: The name of the current file.
831ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum: The number of the line to check.
832ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
833ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Match(r'T(EST|est)', self.current_function):
834ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      base_trigger = self._TEST_TRIGGER
835ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
836ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      base_trigger = self._NORMAL_TRIGGER
837ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    trigger = base_trigger * 2**_VerboseLevel()
838ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
839ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.lines_in_function > trigger:
840ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error_level = int(math.log(self.lines_in_function / base_trigger, 2))
841ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
842ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if error_level > 5:
843ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error_level = 5
844ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/fn_size', error_level,
845ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Small and focused functions are preferred:'
846ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            ' %s has %d non-comment lines'
847ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            ' (error triggered by exceeding %d lines).'  % (
848ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                self.current_function, self.lines_in_function, trigger))
849ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
850ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def End(self):
851ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Stop analyzing function body."""
852ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.in_a_function = False
853ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
854ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
855ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _IncludeError(Exception):
856ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Indicates a problem with the include order in a file."""
857ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  pass
858ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
859ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
860ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass FileInfo:
861ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Provides utility functions for filenames.
862ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
863ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  FileInfo provides easy access to the components of a file's path
864ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  relative to the project root.
865ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
866ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
867ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, filename):
868ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self._filename = filename
869ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
870ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def FullName(self):
871ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Make Windows paths like Unix."""
872ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return os.path.abspath(self._filename).replace('\\', '/')
873ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
874ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def RepositoryName(self):
875ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """FullName after removing the local path to the repository.
876ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
877ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    If we have a real absolute path name here we can try to do something smart:
878ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    detecting the root of the checkout and truncating /path/to/checkout from
879ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    the name so that we get header guards that don't include things like
880ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    "C:\Documents and Settings\..." or "/home/username/..." in them and thus
881ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    people on different computers who have checked the source out to different
882ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    locations won't see bogus errors.
883ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
884ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    fullname = self.FullName()
885ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
886ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if os.path.exists(fullname):
887ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      project_dir = os.path.dirname(fullname)
888ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
889ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if os.path.exists(os.path.join(project_dir, ".svn")):
890ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # If there's a .svn file in the current directory, we recursively look
891ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # up the directory tree for the top of the SVN checkout
892ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        root_dir = project_dir
893ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        one_up_dir = os.path.dirname(root_dir)
894ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        while os.path.exists(os.path.join(one_up_dir, ".svn")):
895ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          root_dir = os.path.dirname(root_dir)
896ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          one_up_dir = os.path.dirname(one_up_dir)
897ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
898ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        prefix = os.path.commonprefix([root_dir, project_dir])
899ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return fullname[len(prefix) + 1:]
900ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
901ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
902ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # searching up from the current path.
903ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      root_dir = os.path.dirname(fullname)
904ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      while (root_dir != os.path.dirname(root_dir) and
905ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             not os.path.exists(os.path.join(root_dir, ".git")) and
906ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             not os.path.exists(os.path.join(root_dir, ".hg")) and
907ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang             not os.path.exists(os.path.join(root_dir, ".svn"))):
908ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        root_dir = os.path.dirname(root_dir)
909ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
910ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (os.path.exists(os.path.join(root_dir, ".git")) or
911ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          os.path.exists(os.path.join(root_dir, ".hg")) or
912ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          os.path.exists(os.path.join(root_dir, ".svn"))):
913ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        prefix = os.path.commonprefix([root_dir, project_dir])
914ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return fullname[len(prefix) + 1:]
915ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
916ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Don't know what to do; header guard warnings may be wrong...
917ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return fullname
918ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
919ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Split(self):
920ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Splits the file into the directory, basename, and extension.
921ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
922ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    For 'chrome/browser/browser.cc', Split() would
923ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return ('chrome/browser', 'browser', '.cc')
924ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
925ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
926ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      A tuple of (directory, basename, extension).
927ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
928ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
929ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    googlename = self.RepositoryName()
930ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    project, rest = os.path.split(googlename)
931ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (project,) + os.path.splitext(rest)
932ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
933ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def BaseName(self):
934ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """File base name - text after the final slash, before the final period."""
935ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return self.Split()[1]
936ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
937ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Extension(self):
938ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """File extension - text following the final period."""
939ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return self.Split()[2]
940ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
941ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def NoExtension(self):
942ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """File has no source file extension."""
943ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return '/'.join(self.Split()[0:2])
944ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
945ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def IsSource(self):
946ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """File has a source file extension."""
947ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
948ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
949ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
950ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _ShouldPrintError(category, confidence, linenum):
951ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """If confidence >= verbose, category passes filter and is not suppressed."""
952ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
953ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # There are three ways we might decide not to print an error message:
954ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # a "NOLINT(category)" comment appears in the source,
955ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # the verbosity level isn't high enough, or the filters filter it out.
956ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if IsErrorSuppressedByNolint(category, linenum):
957ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
958ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if confidence < _cpplint_state.verbose_level:
959ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
960ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
961ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  is_filtered = False
962ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for one_filter in _Filters():
963ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if one_filter.startswith('-'):
964ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if category.startswith(one_filter[1:]):
965ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        is_filtered = True
966ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif one_filter.startswith('+'):
967ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if category.startswith(one_filter[1:]):
968ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        is_filtered = False
969ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
970ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      assert False  # should have been checked for in SetFilter.
971ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if is_filtered:
972ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
973ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
974ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return True
975ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
976ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
977ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef Error(filename, linenum, category, confidence, message):
978ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Logs the fact we've found a lint error.
979ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
980ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  We log where the error was found, and also our confidence in the error,
981ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  that is, how certain we are this is a legitimate style regression, and
982ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  not a misidentification or a use that's sometimes justified.
983ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
984ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  False positives can be suppressed by the use of
985ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  "cpplint(category)"  comments on the offending line.  These are
986ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  parsed into _error_suppressions.
987ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
988ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
989ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the file containing the error.
990ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line containing the error.
991ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    category: A string used to describe the "category" this bug
992ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      falls under: "whitespace", say, or "runtime".  Categories
993ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      may have a hierarchy separated by slashes: "whitespace/indent".
994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    confidence: A number from 1-5 representing a confidence score for
995ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      the error, with 5 meaning that we are certain of the problem,
996ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      and 1 meaning that it could be a legitimate construct.
997ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    message: The error message.
998ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
999ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if _ShouldPrintError(category, confidence, linenum):
1000ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _cpplint_state.IncrementErrorCount(category)
1001ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if _cpplint_state.output_format == 'vs7':
1002ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      sys.stderr.write('%s(%s):  %s  [%s] [%d]\n' % (
1003ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          filename, linenum, message, category, confidence))
1004b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif _cpplint_state.output_format == 'eclipse':
1005b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      sys.stderr.write('%s:%s: warning: %s  [%s] [%d]\n' % (
1006b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          filename, linenum, message, category, confidence))
1007ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
1008ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      sys.stderr.write('%s:%s:  %s  [%s] [%d]\n' % (
1009ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          filename, linenum, message, category, confidence))
1010ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1011ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1012b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
1013ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1014ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
1015ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Matches strings.  Escape codes should already be removed by ESCAPES.
1016ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
1017ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Matches characters.  Escape codes should already be removed by ESCAPES.
1018ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
1019ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Matches multi-line C++ comments.
1020ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# This RE is a little bit more complicated than one might expect, because we
1021ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# have to take care of space removals tools so we can handle comments inside
1022ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# statements better.
1023ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# The current rule is: We only clear spaces from both sides when we're at the
1024ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# end of the line. Otherwise, we try to remove spaces from the right side,
1025ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# if this doesn't work we try on left side but only if there's a non-character
1026ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# on the right.
1027ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
1028ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    r"""(\s*/\*.*\*/\s*$|
1029ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            /\*.*\*/\s+|
1030ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         \s+/\*.*\*/(?=\W)|
1031ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            /\*.*\*/)""", re.VERBOSE)
1032ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1033ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1034ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef IsCppString(line):
1035ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Does line terminate so, that the next symbol is in string constant.
1036ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1037ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  This function does not consider single-line nor multi-line comments.
1038ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1039ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1040ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: is a partial line of code starting from the 0..n.
1041ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1042ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
1043ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True, if next character appended to 'line' is inside a
1044ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    string constant.
1045ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1046ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1047ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = line.replace(r'\\', 'XX')  # after this, \\" does not match to \"
1048ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
1049ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1050ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1051b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CleanseRawStrings(raw_lines):
1052b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Removes C++11 raw strings from lines.
1053b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1054b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    Before:
1055b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      static const char kData[] = R"(
1056b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          multi-line string
1057b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          )";
1058b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1059b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    After:
1060b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      static const char kData[] = ""
1061b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          (replaced by blank line)
1062b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          "";
1063b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1064b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
1065b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    raw_lines: list of raw lines.
1066b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1067b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Returns:
1068b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    list of lines with C++11 raw strings replaced by empty strings.
1069b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
1070b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1071b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  delimiter = None
1072b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  lines_without_raw_strings = []
1073b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  for line in raw_lines:
1074b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if delimiter:
1075b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Inside a raw string, look for the end
1076b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      end = line.find(delimiter)
1077b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if end >= 0:
1078b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Found the end of the string, match leading space for this
1079b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # line and resume copying the original lines, and also insert
1080b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # a "" on the last line.
1081b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        leading_space = Match(r'^(\s*)\S', line)
1082b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        line = leading_space.group(1) + '""' + line[end + len(delimiter):]
1083b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        delimiter = None
1084b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      else:
1085b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Haven't found the end yet, append a blank line.
1086b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        line = ''
1087b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1088b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    else:
1089b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Look for beginning of a raw string.
1090b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # See 2.14.15 [lex.string] for syntax.
1091b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1092b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if matched:
1093b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        delimiter = ')' + matched.group(2) + '"'
1094b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1095b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        end = matched.group(3).find(delimiter)
1096b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if end >= 0:
1097b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          # Raw string ended on same line
1098b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          line = (matched.group(1) + '""' +
1099b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                  matched.group(3)[end + len(delimiter):])
1100b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          delimiter = None
1101b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        else:
1102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          # Start of a multi-line raw string
1103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          line = matched.group(1) + '""'
1104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    lines_without_raw_strings.append(line)
1106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # TODO(unknown): if delimiter is not None here, we might want to
1108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # emit a warning for unterminated string.
1109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return lines_without_raw_strings
1110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FindNextMultiLineCommentStart(lines, lineix):
1113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Find the beginning marker for a multiline comment."""
1114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while lineix < len(lines):
1115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if lines[lineix].strip().startswith('/*'):
1116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Only return this marker if the comment goes beyond this line
1117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if lines[lineix].strip().find('*/', 2) < 0:
1118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return lineix
1119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lineix += 1
1120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return len(lines)
1121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FindNextMultiLineCommentEnd(lines, lineix):
1124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """We are inside a comment, find the end marker."""
1125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while lineix < len(lines):
1126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if lines[lineix].strip().endswith('*/'):
1127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return lineix
1128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lineix += 1
1129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return len(lines)
1130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef RemoveMultiLineCommentsFromRange(lines, begin, end):
1133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Clears a range of lines for multi-line comments."""
1134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Having // dummy comments makes the lines non-empty, so we will not get
1135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # unnecessary blank line warnings later in the code.
1136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for i in range(begin, end):
1137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lines[i] = '// dummy'
1138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef RemoveMultiLineComments(filename, lines, error):
1141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Removes multiline (c-style) comments from lines."""
1142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  lineix = 0
1143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while lineix < len(lines):
1144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
1145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if lineix_begin >= len(lines):
1146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return
1147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
1148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if lineix_end >= len(lines):
1149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
1150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Could not find end of multi-line comment')
1151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return
1152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
1153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lineix = lineix_end + 1
1154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CleanseComments(line):
1157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Removes //-comments and single-line C-style /* */ comments.
1158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: A line of C++ source.
1161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
1163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The line with single-line comments removed.
1164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  commentpos = line.find('//')
1166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if commentpos != -1 and not IsCppString(line[:commentpos]):
1167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line = line[:commentpos].rstrip()
1168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # get rid of /* ... */
1169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
1170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass CleansedLines(object):
1173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Holds 3 copies of all lines with different preprocessing applied to them.
1174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  1) elided member contains lines without strings and comments,
1176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  2) lines member contains lines without comments, and
1177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  3) raw_lines member contains all the lines without processing.
1178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  All these three members are of <type 'list'>, and of the same length.
1179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, lines):
1182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.elided = []
1183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.lines = []
1184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.raw_lines = lines
1185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.num_lines = len(lines)
1186b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    self.lines_without_raw_strings = CleanseRawStrings(lines)
1187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    for linenum in range(len(self.lines_without_raw_strings)):
1188b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      self.lines.append(CleanseComments(
1189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          self.lines_without_raw_strings[linenum]))
1190b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
1191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.elided.append(CleanseComments(elided))
1192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def NumLines(self):
1194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Returns the number of lines represented."""
1195ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return self.num_lines
1196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  @staticmethod
1198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def _CollapseStrings(elided):
1199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Collapses strings and chars on a line to simple "" or '' blocks.
1200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    We nix strings first so we're not fooled by text like '"http://"'
1202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
1204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elided: The line being processed.
1205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
1207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      The line with collapsed strings.
1208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not _RE_PATTERN_INCLUDE.match(elided):
1210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Remove escaped characters first to make quote/single quote collapsing
1211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # basic.  Things that look like escaped characters shouldn't occur
1212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # outside of strings and chars.
1213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
1214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
1215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
1216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return elided
1217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1218ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1219ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar):
1220ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Find the position just after the matching endchar.
1221ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1223ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: a CleansedLines line.
1224ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    startpos: start searching at this position.
1225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    depth: nesting level at startpos.
1226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    startchar: expression opening character.
1227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    endchar: expression closing character.
1228ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1229ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
1230b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    On finding matching endchar: (index just after matching endchar, 0)
1231b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    Otherwise: (-1, new depth at end of this line)
1232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for i in xrange(startpos, len(line)):
1234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if line[i] == startchar:
1235ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      depth += 1
1236ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif line[i] == endchar:
1237ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      depth -= 1
1238ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if depth == 0:
1239b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return (i + 1, 0)
1240b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return (-1, depth)
1241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1242ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CloseExpression(clean_lines, linenum, pos):
1244b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """If input points to ( or { or [ or <, finds the position that closes it.
1245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1246b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
1247ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  linenum/pos that correspond to the closing of the expression.
1248ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1249ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1250ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
1251ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
1252ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pos: A position on the line.
1253ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
1255ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    A tuple (line, linenum, pos) pointer *past* the closing brace, or
1256ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    (line, len(lines), -1) if we never find a close.  Note we ignore
1257ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    strings and comments when matching; and the line we return is the
1258ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'cleansed' line at linenum.
1259ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1261ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
1262ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  startchar = line[pos]
1263b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if startchar not in '({[<':
1264ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (line, clean_lines.NumLines(), -1)
1265ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if startchar == '(': endchar = ')'
1266ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if startchar == '[': endchar = ']'
1267ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if startchar == '{': endchar = '}'
1268b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if startchar == '<': endchar = '>'
1269ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1270ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check first line
1271b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  (end_pos, num_open) = FindEndOfExpressionInLine(
1272b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      line, pos, 0, startchar, endchar)
1273ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if end_pos > -1:
1274ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (line, linenum, end_pos)
1275b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1276b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Continue scanning forward
1277ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while linenum < clean_lines.NumLines() - 1:
1278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum += 1
1279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line = clean_lines.elided[linenum]
1280b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (end_pos, num_open) = FindEndOfExpressionInLine(
1281b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        line, 0, num_open, startchar, endchar)
1282b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if end_pos > -1:
1283b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return (line, linenum, end_pos)
1284ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1285ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Did not find endchar before end of file, give up
1286ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return (line, clean_lines.NumLines(), -1)
1287ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1288b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1289b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef FindStartOfExpressionInLine(line, endpos, depth, startchar, endchar):
1290b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Find position at the matching startchar.
1291b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1292b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  This is almost the reverse of FindEndOfExpressionInLine, but note
1293b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  that the input position and returned position differs by 1.
1294b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1295b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
1296b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    line: a CleansedLines line.
1297b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    endpos: start searching at this position.
1298b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    depth: nesting level at endpos.
1299b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    startchar: expression opening character.
1300b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    endchar: expression closing character.
1301b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Returns:
1303b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    On finding matching startchar: (index at matching startchar, 0)
1304b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    Otherwise: (-1, new depth at beginning of this line)
1305b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
1306b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  for i in xrange(endpos, -1, -1):
1307b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if line[i] == endchar:
1308b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      depth += 1
1309b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif line[i] == startchar:
1310b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      depth -= 1
1311b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if depth == 0:
1312b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return (i, 0)
1313b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return (-1, depth)
1314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1315b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1316b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef ReverseCloseExpression(clean_lines, linenum, pos):
1317b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """If input points to ) or } or ] or >, finds the position that opens it.
1318b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1319b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1320b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  linenum/pos that correspond to the opening of the expression.
1321b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1322b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
1323b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    clean_lines: A CleansedLines instance containing the file.
1324b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    linenum: The number of the line to check.
1325b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    pos: A position on the line.
1326b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1327b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Returns:
1328b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    A tuple (line, linenum, pos) pointer *at* the opening brace, or
1329b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (line, 0, -1) if we never find the matching opening brace.  Note
1330b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    we ignore strings and comments when matching; and the line we
1331b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return is the 'cleansed' line at linenum.
1332b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
1333b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  line = clean_lines.elided[linenum]
1334b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  endchar = line[pos]
1335b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if endchar not in ')}]>':
1336b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return (line, 0, -1)
1337b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if endchar == ')': startchar = '('
1338b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if endchar == ']': startchar = '['
1339b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if endchar == '}': startchar = '{'
1340b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if endchar == '>': startchar = '<'
1341b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1342b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Check last line
1343b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  (start_pos, num_open) = FindStartOfExpressionInLine(
1344b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      line, pos, 0, startchar, endchar)
1345b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if start_pos > -1:
1346b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return (line, linenum, start_pos)
1347b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1348b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Continue scanning backward
1349b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while linenum > 0:
1350b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    linenum -= 1
1351b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    line = clean_lines.elided[linenum]
1352b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (start_pos, num_open) = FindStartOfExpressionInLine(
1353b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        line, len(line) - 1, num_open, startchar, endchar)
1354b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if start_pos > -1:
1355b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return (line, linenum, start_pos)
1356b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1357b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Did not find startchar before beginning of file, give up
1358b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return (line, 0, -1)
1359b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1360b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForCopyright(filename, lines, error):
1362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Logs an error if no Copyright message appears at the top of the file."""
1363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We'll say it should occur by line 10. Don't forget there's a
1365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # dummy line at the front.
1366ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for line in xrange(1, min(len(lines), 11)):
1367ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if re.search(r'Copyright', lines[line], re.I): break
1368ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:                       # means no copyright line was found
1369ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, 0, 'legal/copyright', 5,
1370ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'No copyright message found.  '
1371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'You should have a line: "Copyright [year] <Copyright Owner>"')
1372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef GetHeaderGuardCPPVariable(filename):
1375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Returns the CPP variable that should be used as a header guard.
1376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of a C++ header file.
1379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
1381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The CPP variable that should be used as a header guard in the
1382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    named file.
1383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Restores original filename in case that cpplint is invoked from Emacs's
1387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # flymake.
1388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename = re.sub(r'_flymake\.h$', '.h', filename)
1389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
1390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  fileinfo = FileInfo(filename)
1392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  file_path_from_root = fileinfo.RepositoryName()
1393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if _root:
1394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
1395ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_'
1396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1398ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForHeaderGuard(filename, lines, error):
1399ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks that the file contains a header guard.
1400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Logs an error if no #ifndef header guard is present.  For other
1402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  headers, checks that the full pathname is used.
1403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the C++ header file.
1406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lines: An array of strings, each representing a line of the file.
1407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  cppvar = GetHeaderGuardCPPVariable(filename)
1411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ifndef = None
1413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ifndef_linenum = 0
1414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  define = None
1415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  endif = None
1416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  endif_linenum = 0
1417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for linenum, line in enumerate(lines):
1418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linesplit = line.split()
1419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if len(linesplit) >= 2:
1420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # find the first occurrence of #ifndef and #define, save arg
1421ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not ifndef and linesplit[0] == '#ifndef':
1422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # set ifndef to the header guard presented on the #ifndef line.
1423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ifndef = linesplit[1]
1424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        ifndef_linenum = linenum
1425ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not define and linesplit[0] == '#define':
1426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        define = linesplit[1]
1427ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # find the last occurrence of #endif, save entire line
1428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if line.startswith('#endif'):
1429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      endif = line
1430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      endif_linenum = linenum
1431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not ifndef:
1433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, 0, 'build/header_guard', 5,
1434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'No #ifndef header guard found, suggested CPP variable is: %s' %
1435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          cppvar)
1436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
1437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not define:
1439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, 0, 'build/header_guard', 5,
1440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'No #define header guard found, suggested CPP variable is: %s' %
1441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          cppvar)
1442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
1443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
1445ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # for backward compatibility.
1446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if ifndef != cppvar:
1447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error_level = 0
1448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if ifndef != cppvar + '_':
1449ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error_level = 5
1450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum,
1452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            error)
1453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, ifndef_linenum, 'build/header_guard', error_level,
1454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '#ifndef header guard has wrong style, please use: %s' % cppvar)
1455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if define != ifndef:
1457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, 0, 'build/header_guard', 5,
1458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '#ifndef and #define don\'t match, suggested CPP variable is: %s' %
1459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          cppvar)
1460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
1461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if endif != ('#endif  // %s' % cppvar):
1463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error_level = 0
1464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if endif != ('#endif  // %s' % (cppvar + '_')):
1465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error_level = 5
1466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum,
1468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            error)
1469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, endif_linenum, 'build/header_guard', error_level,
1470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '#endif line should be "#endif  // %s"' % cppvar)
1471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1473b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CheckForBadCharacters(filename, lines, error):
1474b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Logs an error for each line containing bad characters.
1475b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1476b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Two kinds of bad characters:
1477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1478b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  1. Unicode replacement characters: These indicate that either the file
1479b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  contained invalid UTF-8 (likely) or Unicode replacement characters (which
1480b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  it shouldn't).  Note that it's possible for this to throw off line
1481b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  numbering if the invalid UTF-8 occurred adjacent to a newline.
1482b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1483b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  2. NUL bytes.  These are problematic for some tools.
1484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
1487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lines: An array of strings, each representing a line of the file.
1488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for linenum, line in enumerate(lines):
1491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if u'\ufffd' in line:
1492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/utf8', 5,
1493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Line contains invalid UTF-8 (or Unicode replacement character).')
1494b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if '\0' in line:
1495b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
1496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForNewlineAtEOF(filename, lines, error):
1499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Logs an error if there is no newline char at the end of the file.
1500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
1503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lines: An array of strings, each representing a line of the file.
1504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The array lines() was created by adding two newlines to the
1508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # original file (go figure), then splitting on \n.
1509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # To verify that the file ends in \n, we just have to make sure the
1510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # last-but-two element of lines() exists and is empty.
1511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if len(lines) < 3 or lines[-2]:
1512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
1513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Could not find a newline character at the end of the file.')
1514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
1517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Logs an error if we see /* ... */ or "..." that extend past one line.
1518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  /* ... */ comments are legit inside macros, for one line.
1520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Otherwise, we prefer // comments, so it's ok to warn about the
1521ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  other.  Likewise, it's ok for strings to extend across multiple
1522ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  lines, as long as a line continuation character (backslash)
1523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  terminates each line. Although not currently prohibited by the C++
1524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  style guide, it's ugly and unnecessary. We don't do well with either
1525ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  in this lint program, so we warn about both.
1526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
1529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
1530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
1531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
1534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Remove all \\ (escaped backslashes) from the line. They are OK, and the
1536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # second (escaped) slash may trigger later \" detection erroneously.
1537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = line.replace('\\\\', '')
1538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if line.count('/*') > line.count('*/'):
1540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'readability/multiline_comment', 5,
1541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Complex multi-line /*...*/-style comment found. '
1542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Lint may give bogus warnings.  '
1543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Consider replacing these with //-style comments, '
1544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'with #if 0...#endif, '
1545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'or with more clearly structured multi-line comments.')
1546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (line.count('"') - line.count('\\"')) % 2:
1548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'readability/multiline_string', 5,
1549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Multi-line string ("...") found.  This lint script doesn\'t '
1550b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'do well with such strings, and may give bogus warnings.  '
1551b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'Use C++11 raw strings or concatenation instead.')
1552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangthreading_list = (
1555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('asctime(', 'asctime_r('),
1556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('ctime(', 'ctime_r('),
1557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('getgrgid(', 'getgrgid_r('),
1558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('getgrnam(', 'getgrnam_r('),
1559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('getlogin(', 'getlogin_r('),
1560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('getpwnam(', 'getpwnam_r('),
1561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('getpwuid(', 'getpwuid_r('),
1562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('gmtime(', 'gmtime_r('),
1563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('localtime(', 'localtime_r('),
1564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('rand(', 'rand_r('),
1565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('strtok(', 'strtok_r('),
1566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('ttyname(', 'ttyname_r('),
1567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    )
1568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckPosixThreading(filename, clean_lines, linenum, error):
1571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for calls to thread-unsafe functions.
1572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Much code has been originally written without consideration of
1574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  multi-threading. Also, engineers are relying on their old experience;
1575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  they have learned posix before threading extensions were added. These
1576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  tests guide the engineers to use thread-safe functions (when using
1577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  posix directly).
1578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
1581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
1582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
1583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
1586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for single_thread_function, multithread_safe_function in threading_list:
1587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ix = line.find(single_thread_function)
1588b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
1589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and
1590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                line[ix - 1] not in ('_', '.', '>'))):
1591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'runtime/threadsafe_fn', 2,
1592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Consider using ' + multithread_safe_function +
1593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '...) instead of ' + single_thread_function +
1594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '...) for improved thread safety.')
1595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1597b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CheckVlogArguments(filename, clean_lines, linenum, error):
1598b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Checks that VLOG() is only used for defining a logging level.
1599b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1600b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
1601b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  VLOG(FATAL) are not.
1602b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1603b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
1604b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    filename: The name of the current file.
1605b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    clean_lines: A CleansedLines instance containing the file.
1606b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    linenum: The number of the line to check.
1607b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    error: The function to call with any errors found.
1608b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
1609b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  line = clean_lines.elided[linenum]
1610b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
1611b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    error(filename, linenum, 'runtime/vlog', 5,
1612b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'VLOG() should be used with numeric verbosity level.  '
1613b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'Use LOG() if you want symbolic severity levels.')
1614b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1615b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Matches invalid increment: *count++, which moves pointer instead of
1617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# incrementing a value.
1618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_INVALID_INCREMENT = re.compile(
1619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    r'^\s*\*\w+(\+\+|--);')
1620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckInvalidIncrement(filename, clean_lines, linenum, error):
1623ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for invalid increment *count++.
1624ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1625ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  For example following function:
1626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  void increment_counter(int* count) {
1627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    *count++;
1628ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
1629ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  is invalid, because it effectively does count++, moving pointer, and should
1630ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  be replaced with ++*count, (*count)++ or *count += 1.
1631ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
1633ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
1634ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
1635ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
1636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
1637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
1638ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
1639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if _RE_PATTERN_INVALID_INCREMENT.match(line):
1640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/invalid_increment', 5,
1641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Changing pointer instead of value (or unused value of operator*).')
1642ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _BlockInfo(object):
1645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Stores information about a generic block of code."""
1646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, seen_open_brace):
1648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.seen_open_brace = seen_open_brace
1649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.open_parentheses = 0
1650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.inline_asm = _NO_ASM
1651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CheckBegin(self, filename, clean_lines, linenum, error):
1653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Run checks that applies to text up to the opening brace.
1654ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1655ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    This is mostly for checking the text after the class identifier
1656ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    and the "{", usually where the base class is specified.  For other
1657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    blocks, there isn't much to check, so we always pass.
1658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
1660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename: The name of the current file.
1661ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      clean_lines: A CleansedLines instance containing the file.
1662ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum: The number of the line to check.
1663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error: The function to call with any errors found.
1664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pass
1666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CheckEnd(self, filename, clean_lines, linenum, error):
1668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Run checks that applies to text after the closing brace.
1669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    This is mostly used for checking end of namespace comments.
1671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
1673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename: The name of the current file.
1674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      clean_lines: A CleansedLines instance containing the file.
1675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum: The number of the line to check.
1676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error: The function to call with any errors found.
1677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pass
1679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _ClassInfo(_BlockInfo):
1682ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Stores information about a class."""
1683ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1684ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, name, class_or_struct, clean_lines, linenum):
1685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _BlockInfo.__init__(self, False)
1686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.name = name
1687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.starting_linenum = linenum
1688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.is_derived = False
1689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if class_or_struct == 'struct':
1690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.access = 'public'
1691b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      self.is_struct = True
1692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
1693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.access = 'private'
1694b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      self.is_struct = False
1695b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1696b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Remember initial indentation level for this class.  Using raw_lines here
1697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # instead of elided to account for leading comments.
1698b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum])
1699b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if initial_indent:
1700b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      self.class_indent = len(initial_indent.group(1))
1701b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    else:
1702b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      self.class_indent = 0
1703ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1704ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Try to find the end of the class.  This will be confused by things like:
1705ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   class A {
1706ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   } *x = { ...
1707ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1708ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # But it's still good enough for CheckSectionSpacing.
1709ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.last_line = 0
1710ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    depth = 0
1711ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for i in range(linenum, clean_lines.NumLines()):
1712ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = clean_lines.elided[i]
1713ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      depth += line.count('{') - line.count('}')
1714ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not depth:
1715ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self.last_line = i
1716ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
1717ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1718ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CheckBegin(self, filename, clean_lines, linenum, error):
1719ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Look for a bare ':'
1720ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
1721ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.is_derived = True
1722ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1723b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  def CheckEnd(self, filename, clean_lines, linenum, error):
1724b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Check that closing brace is aligned with beginning of the class.
1725b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Only do this if the closing brace is indented by only whitespaces.
1726b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # This means we will not check single-line class definitions.
1727b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    indent = Match(r'^( *)\}', clean_lines.elided[linenum])
1728b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if indent and len(indent.group(1)) != self.class_indent:
1729b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if self.is_struct:
1730b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        parent = 'struct ' + self.name
1731b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      else:
1732b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        parent = 'class ' + self.name
1733b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      error(filename, linenum, 'whitespace/indent', 3,
1734b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            'Closing brace should be aligned with beginning of %s' % parent)
1735b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1736ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1737ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _NamespaceInfo(_BlockInfo):
1738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Stores information about a namespace."""
1739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, name, linenum):
1741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _BlockInfo.__init__(self, False)
1742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.name = name or ''
1743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.starting_linenum = linenum
1744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def CheckEnd(self, filename, clean_lines, linenum, error):
1746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Check end of namespace comments."""
1747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line = clean_lines.raw_lines[linenum]
1748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Check how many lines is enclosed in this namespace.  Don't issue
1750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # warning for missing namespace comments if there aren't enough
1751ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # lines.  However, do apply checks if there is already an end of
1752ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # namespace comment and it's incorrect.
1753ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1754ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # TODO(unknown): We always want to check end of namespace comments
1755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # if a namespace is large, but sometimes we also want to apply the
1756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # check if a short namespace contained nontrivial things (something
1757ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # other than forward declarations).  There is currently no logic on
1758ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # deciding what these nontrivial things are, so this check is
1759ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # triggered by namespace size only, which works most of the time.
1760ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (linenum - self.starting_linenum < 10
1761ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)):
1762ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return
1763ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1764ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Look for matching comment at end of namespace.
1765ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1766ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Note that we accept C style "/* */" comments for terminating
1767ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # namespaces, so that code that terminate namespaces inside
1768b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # preprocessor macros can be cpplint clean.
1769ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1770ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # We also accept stuff like "// end of namespace <name>." with the
1771ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # period at the end.
1772ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1773ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Besides these, we don't accept anything else, otherwise we might
1774ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # get false negatives when existing comment is a substring of the
1775b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # expected namespace.
1776ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.name:
1777ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Named namespace
1778ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
1779ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    r'[\*/\.\\\s]*$'),
1780ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   line):
1781ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'readability/namespace', 5,
1782ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Namespace should be terminated with "// namespace %s"' %
1783ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              self.name)
1784ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
1785ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Anonymous namespace
1786ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
1787ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'readability/namespace', 5,
1788ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Namespace should be terminated with "// namespace"')
1789ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1790ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1791ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _PreprocessorInfo(object):
1792ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Stores checkpoints of nesting stacks when #if/#else is seen."""
1793ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1794ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self, stack_before_if):
1795ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # The entire nesting stack before #if
1796ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.stack_before_if = stack_before_if
1797ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1798ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # The entire nesting stack up to #else
1799ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.stack_before_else = []
1800ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1801ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Whether we have already seen #else or #elif
1802ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.seen_else = False
1803ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1804ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1805ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangclass _NestingState(object):
1806ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Holds states related to parsing braces."""
1807ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1808ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def __init__(self):
1809ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Stack for tracking all braces.  An object is pushed whenever we
1810ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # see a "{", and popped when we see a "}".  Only 3 types of
1811ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # objects are possible:
1812ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # - _ClassInfo: a class or struct.
1813ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # - _NamespaceInfo: a namespace.
1814ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # - _BlockInfo: some other type of block.
1815ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.stack = []
1816ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1817ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Stack of _PreprocessorInfo objects.
1818ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.pp_stack = []
1819ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1820ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def SeenOpenBrace(self):
1821ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Check if we have seen the opening brace for the innermost block.
1822ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1823ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
1824ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      True if we have seen the opening brace, False if the innermost
1825ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      block is still expecting an opening brace.
1826ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1827ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (not self.stack) or self.stack[-1].seen_open_brace
1828ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1829ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def InNamespaceBody(self):
1830ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Check if we are currently one level inside a namespace body.
1831ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1832ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
1833ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      True if top of the stack is a namespace block, False otherwise.
1834ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1835ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
1836ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1837ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def UpdatePreprocessor(self, line):
1838ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Update preprocessor stack.
1839ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1840ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    We need to handle preprocessors due to classes like this:
1841ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #ifdef SWIG
1842ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      struct ResultDetailsPageElementExtensionPoint {
1843ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #else
1844ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      struct ResultDetailsPageElementExtensionPoint : public Extension {
1845ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #endif
1846ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1847ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    We make the following assumptions (good enough for most files):
1848ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    - Preprocessor condition evaluates to true from #if up to first
1849ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #else/#elif/#endif.
1850ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1851ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    - Preprocessor condition evaluates to false from #else/#elif up
1852ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      to #endif.  We still perform lint checks on these lines, but
1853ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      these do not affect nesting stack.
1854ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1855ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
1856ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line: current line to check.
1857ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1858ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
1859ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Beginning of #if block, save the nesting stack here.  The saved
1860ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # stack will allow us to restore the parsing state in the #else case.
1861ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
1862ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif Match(r'^\s*#\s*(else|elif)\b', line):
1863ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Beginning of #else block
1864ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self.pp_stack:
1865ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if not self.pp_stack[-1].seen_else:
1866ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # This is the first #else or #elif block.  Remember the
1867ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # whole nesting stack up to this point.  This is what we
1868ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # keep after the #endif.
1869ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.pp_stack[-1].seen_else = True
1870ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
1871ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1872ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Restore the stack to how it was before the #if
1873ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
1874ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
1875ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # TODO(unknown): unexpected #else, issue warning?
1876ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        pass
1877ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif Match(r'^\s*#\s*endif\b', line):
1878ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # End of #if or #else blocks.
1879ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if self.pp_stack:
1880ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # If we saw an #else, we will need to restore the nesting
1881ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # stack to its former state before the #else, otherwise we
1882ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # will just continue from where we left off.
1883ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if self.pp_stack[-1].seen_else:
1884ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Here we can just use a shallow copy since we are the last
1885ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # reference to it.
1886ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack = self.pp_stack[-1].stack_before_else
1887ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Drop the corresponding #if
1888ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        self.pp_stack.pop()
1889ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
1890ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # TODO(unknown): unexpected #endif, issue warning?
1891ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        pass
1892ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1893ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def Update(self, filename, clean_lines, linenum, error):
1894ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Update nesting state with current line.
1895ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1896ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
1897ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename: The name of the current file.
1898ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      clean_lines: A CleansedLines instance containing the file.
1899ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum: The number of the line to check.
1900ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error: The function to call with any errors found.
1901ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
1902ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line = clean_lines.elided[linenum]
1903ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1904ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Update pp_stack first
1905ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    self.UpdatePreprocessor(line)
1906ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1907ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Count parentheses.  This is to avoid adding struct arguments to
1908ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # the nesting stack.
1909ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.stack:
1910ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      inner_block = self.stack[-1]
1911ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      depth_change = line.count('(') - line.count(')')
1912ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      inner_block.open_parentheses += depth_change
1913ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1914ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Also check if we are starting or ending an inline assembly block.
1915ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if inner_block.inline_asm in (_NO_ASM, _END_ASM):
1916ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if (depth_change != 0 and
1917ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            inner_block.open_parentheses == 1 and
1918ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            _MATCH_ASM.match(line)):
1919ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Enter assembly block
1920ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          inner_block.inline_asm = _INSIDE_ASM
1921ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
1922ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Not entering assembly block.  If previous line was _END_ASM,
1923ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # we will now shift to _NO_ASM state.
1924ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          inner_block.inline_asm = _NO_ASM
1925ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elif (inner_block.inline_asm == _INSIDE_ASM and
1926ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            inner_block.open_parentheses == 0):
1927ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Exit assembly block
1928ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        inner_block.inline_asm = _END_ASM
1929ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1930ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Consume namespace declaration at the beginning of the line.  Do
1931ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # this in a loop so that we catch same line declarations like this:
1932ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   namespace proto2 { namespace bridge { class MessageSet; } }
1933ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    while True:
1934ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Match start of namespace.  The "\b\s*" below catches namespace
1935ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # declarations even if it weren't followed by a whitespace, this
1936ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # is so that we don't confuse our namespace checker.  The
1937ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # missing spaces will be flagged by CheckSpacing.
1938ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
1939ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not namespace_decl_match:
1940ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
1941ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1942ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
1943ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.stack.append(new_namespace)
1944ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1945ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = namespace_decl_match.group(2)
1946ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if line.find('{') != -1:
1947ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        new_namespace.seen_open_brace = True
1948ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        line = line[line.find('{') + 1:]
1949ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1950ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Look for a class declaration in whatever is left of the line
1951ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # after parsing namespaces.  The regexp accounts for decorated classes
1952ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # such as in:
1953ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   class LOCKABLE API Object {
1954ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   };
1955ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1956ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Templates with class arguments may confuse the parser, for example:
1957ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   template <class T
1958ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #             class Comparator = less<T>,
1959ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #             class Vector = vector<T> >
1960ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   class HeapQueue {
1961ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1962ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Because this parser has no nesting state about templates, by the
1963ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # time it saw "class Comparator", it may think that it's a new class.
1964ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Nested templates have a similar problem:
1965ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   template <
1966ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #       typename ExportedType,
1967ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #       typename TupleType,
1968ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #       template <typename, typename> class ImplTemplate>
1969ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
1970ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # To avoid these cases, we ignore classes that are followed by '=' or '>'
1971ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    class_decl_match = Match(
1972ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        r'\s*(template\s*<[\w\s<>,:]*>\s*)?'
1973b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)'
1974b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line)
1975ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (class_decl_match and
1976ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        (not self.stack or self.stack[-1].open_parentheses == 0)):
1977ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.stack.append(_ClassInfo(
1978ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          class_decl_match.group(4), class_decl_match.group(2),
1979ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          clean_lines, linenum))
1980ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = class_decl_match.group(5)
1981ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1982ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If we have not yet seen the opening brace for the innermost block,
1983ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # run checks here.
1984ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not self.SeenOpenBrace():
1985ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
1986ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1987ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Update access control if we are inside a class/struct
1988ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if self.stack and isinstance(self.stack[-1], _ClassInfo):
1989b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      classinfo = self.stack[-1]
1990b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      access_match = Match(
1991b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
1992b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          r':(?:[^:]|$)',
1993b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          line)
1994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if access_match:
1995b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        classinfo.access = access_match.group(2)
1996b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1997b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Check that access keywords are indented +1 space.  Skip this
1998b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # check if the keywords are not preceded by whitespaces.
1999b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        indent = access_match.group(1)
2000b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (len(indent) != classinfo.class_indent + 1 and
2001b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            Match(r'^\s*$', indent)):
2002b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          if classinfo.is_struct:
2003b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            parent = 'struct ' + classinfo.name
2004b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          else:
2005b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            parent = 'class ' + classinfo.name
2006b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          slots = ''
2007b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          if access_match.group(3):
2008b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            slots = access_match.group(3)
2009b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          error(filename, linenum, 'whitespace/indent', 3,
2010b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                '%s%s: should be indented +1 space inside %s' % (
2011b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                    access_match.group(2), slots, parent))
2012ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2013ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Consume braces or semicolons from what's left of the line
2014ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    while True:
2015ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Match first brace, semicolon, or closed parenthesis.
2016ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
2017ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not matched:
2018ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
2019ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2020ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      token = matched.group(1)
2021ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if token == '{':
2022ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # If namespace or class hasn't seen a opening brace yet, mark
2023ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # namespace/class head as complete.  Push a new block onto the
2024ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # stack otherwise.
2025ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if not self.SeenOpenBrace():
2026ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack[-1].seen_open_brace = True
2027ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
2028ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack.append(_BlockInfo(True))
2029ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          if _MATCH_ASM.match(line):
2030ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            self.stack[-1].inline_asm = _BLOCK_ASM
2031ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elif token == ';' or token == ')':
2032ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # If we haven't seen an opening brace yet, but we already saw
2033ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # a semicolon, this is probably a forward declaration.  Pop
2034ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # the stack for these.
2035ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        #
2036ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Similarly, if we haven't seen an opening brace yet, but we
2037ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # already saw a closing parenthesis, then these are probably
2038ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # function arguments with extra "class" or "struct" keywords.
2039ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Also pop these stack for these.
2040ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if not self.SeenOpenBrace():
2041ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack.pop()
2042ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:  # token == '}'
2043ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Perform end of block checks and pop the stack.
2044ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if self.stack:
2045ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2046ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          self.stack.pop()
2047ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = matched.group(2)
2048ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2049ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  def InnermostClass(self):
2050ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """Get class info on the top of the stack.
2051ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2052ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Returns:
2053ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      A _ClassInfo object if we are inside a class, or None otherwise.
2054ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
2055ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for i in range(len(self.stack), 0, -1):
2056ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      classinfo = self.stack[i - 1]
2057ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if isinstance(classinfo, _ClassInfo):
2058ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        return classinfo
2059ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return None
2060ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2061b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  def CheckCompletedBlocks(self, filename, error):
2062b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    """Checks that all classes and namespaces have been completely parsed.
2063ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2064ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Call this when all lines in a file have been processed.
2065ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Args:
2066ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename: The name of the current file.
2067ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error: The function to call with any errors found.
2068ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    """
2069ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Note: This test can result in false positives if #ifdef constructs
2070ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # get in the way of brace matching. See the testBuildClass test in
2071ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # cpplint_unittest.py for an example of this.
2072ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for obj in self.stack:
2073ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if isinstance(obj, _ClassInfo):
2074ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, obj.starting_linenum, 'build/class', 5,
2075ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Failed to find complete declaration of class %s' %
2076ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              obj.name)
2077b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      elif isinstance(obj, _NamespaceInfo):
2078b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        error(filename, obj.starting_linenum, 'build/namespaces', 5,
2079b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Failed to find complete declaration of namespace %s' %
2080b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              obj.name)
2081ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2082ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2083ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForNonStandardConstructs(filename, clean_lines, linenum,
2084ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                  nesting_state, error):
2085b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
2086ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2087ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Complain about several constructs which gcc-2 accepts, but which are
2088ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  not standard C++.  Warning about these in lint is one way to ease the
2089ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  transition to new compilers.
2090ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - put storage class first (e.g. "static const" instead of "const static").
2091ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - "%lld" instead of %qd" in printf-type functions.
2092ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - "%1$d" is non-standard in printf-type functions.
2093ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - "\%" is an undefined character escape sequence.
2094ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - text after #endif is not allowed.
2095ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - invalid inner-style forward declaration.
2096ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  - >? and <? operators, and their >?= and <?= cousins.
2097ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2098ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Additionally, check for constructor/destructor style violations and reference
2099ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  members, as it is very convenient to do so while checking for
2100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  gcc-2 compliance.
2101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nesting_state: A _NestingState instance which maintains information about
2107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the current stack of nested blocks being parsed.
2108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: A callable to which errors are reported, which takes 4 arguments:
2109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           filename, line number, error level, and message
2110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Remove comments from the line, but leave in strings for now.
2113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.lines[linenum]
2114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/printf_format', 3,
2117ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '%q in format strings is deprecated.  Use %ll instead.')
2118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'printf\s*\(.*".*%\d+\$', line):
2120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/printf_format', 2,
2121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '%N$ formats are unconventional.  Try rewriting to avoid them.')
2122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Remove escaped backslashes before looking for undefined escapes.
2124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = line.replace('\\\\', '')
2125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'("|\').*\\(%|\[|\(|{)', line):
2127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/printf_format', 3,
2128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '%, [, (, and { are undefined character escapes.  Unescape them.')
2129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # For the rest, work with both comments and strings removed.
2131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
2132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\b(const|volatile|void|char|short|int|long'
2134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            r'|float|double|signed|unsigned'
2135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            r'|schar|u?int8|u?int16|u?int32|u?int64)'
2136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            r'\s+(register|static|extern|typedef)\b',
2137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            line):
2138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/storage_class', 5,
2139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Storage class (static, extern, typedef, etc) should be first.')
2140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
2142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/endif_comment', 5,
2143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Uncommented text after #endif is non-standard.  Use a comment.')
2144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/forward_decl', 5,
2147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Inner-style forward declarations are invalid.  Remove this line.')
2148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            line):
2151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/deprecated', 3,
2152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '>? and <? (max and min) operators are non-standard and deprecated.')
2153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # TODO(unknown): Could it be expanded safely to arbitrary references,
2156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # without triggering too many false positives? The first
2157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # attempt triggered 5 warnings for mostly benign code in the regtest, hence
2158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # the restriction.
2159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Here's the original regexp, for the reference:
2160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
2161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
2162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/member_string_references', 2,
2163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'const string& members are dangerous. It is much better to use '
2164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'alternatives, such as pointers or simple constants.')
2165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Everything else in this function operates on class declarations.
2167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Return early if the top of the nesting stack is not a class, or if
2168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # the class head is not completed yet.
2169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  classinfo = nesting_state.InnermostClass()
2170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not classinfo or not classinfo.seen_open_brace:
2171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
2172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The class may have been declared with namespace or classname qualifiers.
2174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The constructor and destructor will not have those qualifiers.
2175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  base_classname = classinfo.name.split('::')[-1]
2176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Look for single-argument constructors that aren't marked explicit.
2178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Technically a valid construct, but against style.
2179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)'
2180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               % re.escape(base_classname),
2181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               line)
2182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (args and
2183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      args.group(1) != 'void' and
2184b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&'
2185b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                % re.escape(base_classname), args.group(1).strip())):
2186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/explicit', 5,
2187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Single-argument constructors should be marked explicit.')
2188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckSpacingForFunctionCall(filename, line, linenum, error):
2191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for the correctness of various spacing around function calls.
2192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2195ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: The text of the line to check.
2196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Since function calls often occur inside if/for/while/switch
2201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # expressions - which have their own, more liberal conventions - we
2202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # first see if we should be looking inside such an expression for a
2203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # function call, to which we can apply more strict standards.
2204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  fncall = line    # if there's no control flow construct, look at whole line
2205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for pattern in (r'\bif\s*\((.*)\)\s*{',
2206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  r'\bfor\s*\((.*)\)\s*{',
2207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  r'\bwhile\s*\((.*)\)\s*[{;]',
2208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  r'\bswitch\s*\((.*)\)\s*{'):
2209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(pattern, line)
2210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match:
2211ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      fncall = match.group(1)    # look inside the parens for function calls
2212ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break
2213ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2214ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Except in if/for/while/switch, there should never be space
2215ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # immediately inside parens (eg "f( 3, 4 )").  We make an exception
2216ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # for nested parens ( (a+b) + c ).  Likewise, there should never be
2217ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # a space before a ( when it's a function argument.  I assume it's a
2218ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # function argument when the char before the whitespace is legal in
2219ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # a function name (alnum + _) and we're not starting a macro. Also ignore
2220ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # pointers and references to arrays and functions coz they're too tricky:
2221ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # we use a very simple way to recognize these:
2222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # " (something)(maybe-something)" or
2223ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # " (something)(maybe-something," or
2224ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # " (something)[something]"
2225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Note that we assume the contents of [] to be short enough that
2226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # they'll never need to wrap.
2227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (  # Ignore control structures.
2228b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2229b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                 fncall) and
2230ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Ignore pointers/references to functions.
2231ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
2232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Ignore pointers/references to arrays.
2233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
2234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
2235ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/parens', 4,
2236ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Extra space after ( in function call')
2237ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
2238ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/parens', 2,
2239ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Extra space after (')
2240ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (Search(r'\w\s+\(', fncall) and
2241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Search(r'#\s*define|typedef', fncall) and
2242b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall)):
2243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/parens', 4,
2244ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Extra space before ( in function call')
2245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If the ) is followed only by a newline or a { + newline, assume it's
2246ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # part of a control statement (if/while/etc), and don't complain
2247ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
2248ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # If the closing parenthesis is preceded by only whitespaces,
2249ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # try to give a more descriptive error message.
2250ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Search(r'^\s+\)', fncall):
2251ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/parens', 2,
2252ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Closing ) should be moved to the previous line')
2253ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
2254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/parens', 2,
2255ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Extra space before )')
2256ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2257ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2258ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef IsBlankLine(line):
2259ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Returns true if the given line is blank.
2260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2261ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  We consider a line to be blank if the line is empty or consists of
2262ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  only white spaces.
2263ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2264ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2265ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: A line of a string.
2266ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2267ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
2268ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True, if the given line is blank.
2269ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2270ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return not line or line.isspace()
2271ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2272ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2273ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForFunctionLengths(filename, clean_lines, linenum,
2274ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                            function_state, error):
2275ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Reports for long function bodies.
2276ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2277ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  For an overview why this is done, see:
2278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
2279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2280ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Uses a simplistic algorithm assuming other style guidelines
2281ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  (especially spacing) are followed.
2282ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Only checks unindented functions, so class members are unchecked.
2283ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Trivial bodies are unchecked, so constructors with huge initializer lists
2284ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  may be missed.
2285ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Blank/comment lines are not counted so as to avoid encouraging the removal
2286ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  of vertical space and comments just to get through a lint check.
2287ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  NOLINT *on the last line of a function* disables this check.
2288ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2289ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2290ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2291ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2292ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2293ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_state: Current function name and lines in body so far.
2294ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2295ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2296ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  lines = clean_lines.lines
2297ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = lines[linenum]
2298ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  raw = clean_lines.raw_lines
2299ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  raw_line = raw[linenum]
2300ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  joined_line = ''
2301ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2302ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  starting_func = False
2303ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  regexp = r'(\w(\w|::|\*|\&|\s)*)\('  # decls * & space::name( ...
2304ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match_result = Match(regexp, line)
2305ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match_result:
2306ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If the name is all caps and underscores, figure it's a macro and
2307ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # ignore it, unless it's TEST or TEST_F.
2308ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_name = match_result.group(1).split()[-1]
2309ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if function_name == 'TEST' or function_name == 'TEST_F' or (
2310ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Match(r'[A-Z_]+$', function_name)):
2311ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      starting_func = True
2312ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2313ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if starting_func:
2314ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    body_found = False
2315ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for start_linenum in xrange(linenum, clean_lines.NumLines()):
2316ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      start_line = lines[start_linenum]
2317ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      joined_line += ' ' + start_line.lstrip()
2318ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Search(r'(;|})', start_line):  # Declarations and trivial functions
2319ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        body_found = True
2320ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break                              # ... ignore
2321ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elif Search(r'{', start_line):
2322ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        body_found = True
2323ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        function = Search(r'((\w|:)*)\(', line).group(1)
2324ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if Match(r'TEST', function):    # Handle TEST... macros
2325ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          parameter_regexp = Search(r'(\(.*\))', joined_line)
2326ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          if parameter_regexp:             # Ignore bad syntax
2327ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            function += parameter_regexp.group(1)
2328ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
2329ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          function += '()'
2330ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        function_state.Begin(function)
2331ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
2332ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not body_found:
2333ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # No body for the function (or evidence of a non-function) was found.
2334ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/fn_size', 5,
2335ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Lint failed to find start of function body.')
2336ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif Match(r'^\}\s*$', line):  # function end
2337ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_state.Check(error, filename, linenum)
2338ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_state.End()
2339ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif not Match(r'^\s*$', line):
2340ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_state.Count()  # Count non-blank/non-comment lines.
2341ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2342ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2343ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2344ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2345ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2346ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckComment(comment, filename, linenum, error):
2347ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for common mistakes in TODO comments.
2348ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2349ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2350ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    comment: The text of the comment from the line in question.
2351ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2354ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2355ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = _RE_PATTERN_TODO.match(comment)
2356ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2357ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # One whitespace is correct; zero whitespace is handled elsewhere.
2358ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    leading_whitespace = match.group(1)
2359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if len(leading_whitespace) > 1:
2360ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/todo', 2,
2361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Too many spaces before TODO')
2362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    username = match.group(2)
2364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not username:
2365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/todo', 2,
2366ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Missing username in TODO; it should look like '
2367ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '"// TODO(my_username): Stuff."')
2368ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2369ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    middle_whitespace = match.group(3)
2370b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
2371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if middle_whitespace != ' ' and middle_whitespace != '':
2372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/todo', 2,
2373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'TODO(my_username) should be followed by a space')
2374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckAccess(filename, clean_lines, linenum, nesting_state, error):
2376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for improper use of DISALLOW* macros.
2377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nesting_state: A _NestingState instance which maintains information about
2383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the current stack of nested blocks being parsed.
2384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]  # get rid of comments and strings
2387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
2389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   r'DISALLOW_EVIL_CONSTRUCTORS|'
2390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
2391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not matched:
2392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
2393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo):
2394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if nesting_state.stack[-1].access != 'private':
2395ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/constructors', 3,
2396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '%s must be in the private: section' % matched.group(1))
2397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2398ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
2399ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Found DISALLOW* macro outside a class declaration, or perhaps it
2400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # was used inside a function when it should have been part of the
2401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # class declaration.  We could issue a warning here, but it
2402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # probably resulted in a compiler error already.
2403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pass
2404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FindNextMatchingAngleBracket(clean_lines, linenum, init_suffix):
2407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Find the corresponding > to close a template.
2408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: Current line number.
2412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    init_suffix: Remainder of the current line after the initial <.
2413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
2415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True if a matching bracket exists.
2416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = init_suffix
2418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nesting_stack = ['<']
2419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while True:
2420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Find the next operator that can tell us whether < is used as an
2421ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # opening bracket or as a less-than operator.  We only want to
2422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # warn on the latter case.
2423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
2424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # We could also check all other operators and terminate the search
2425ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # early, e.g. if we got something like this "a<b+c", the "<" is
2426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # most likely a less-than operator, but then we will get false
2427b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # positives for default arguments and other template expressions.
2428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(r'^[^<>(),;\[\]]*([<>(),;\[\]])(.*)$', line)
2429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match:
2430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Found an operator, update nesting stack
2431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      operator = match.group(1)
2432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = match.group(2)
2433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if nesting_stack[-1] == '<':
2435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Expecting closing angle bracket
2436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if operator in ('<', '(', '['):
2437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.append(operator)
2438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator == '>':
2439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.pop()
2440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          if not nesting_stack:
2441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            # Found matching angle bracket
2442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            return True
2443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator == ',':
2444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Got a comma after a bracket, this is most likely a template
2445ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # argument.  We have not seen a closing angle bracket yet, but
2446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # it's probably a few lines later if we look for it, so just
2447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # return early here.
2448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return True
2449ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
2450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Got some other operator.
2451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return False
2452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
2454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Expecting closing parenthesis or closing bracket
2455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if operator in ('<', '(', '['):
2456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.append(operator)
2457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator in (')', ']'):
2458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # We don't bother checking for matching () or [].  If we got
2459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # something like (] or [), it would have been a syntax error.
2460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.pop()
2461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
2463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Scan the next line
2464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum += 1
2465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if linenum >= len(clean_lines.elided):
2466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
2467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = clean_lines.elided[linenum]
2468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Exhausted all remaining lines and still no matching angle bracket.
2470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Most likely the input was incomplete, otherwise we should have
2471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # seen a semicolon and returned early.
2472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return True
2473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FindPreviousMatchingAngleBracket(clean_lines, linenum, init_prefix):
2476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Find the corresponding < that started a template.
2477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: Current line number.
2481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    init_prefix: Part of the current line before the initial >.
2482ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
2484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True if a matching bracket exists.
2485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = init_prefix
2487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nesting_stack = ['>']
2488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while True:
2489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Find the previous operator
2490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(r'^(.*)([<>(),;\[\]])[^<>(),;\[\]]*$', line)
2491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match:
2492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Found an operator, update nesting stack
2493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      operator = match.group(2)
2494ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = match.group(1)
2495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if nesting_stack[-1] == '>':
2497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Expecting opening angle bracket
2498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if operator in ('>', ')', ']'):
2499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.append(operator)
2500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator == '<':
2501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.pop()
2502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          if not nesting_stack:
2503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            # Found matching angle bracket
2504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            return True
2505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator == ',':
2506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Got a comma before a bracket, this is most likely a
2507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # template argument.  The opening angle bracket is probably
2508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # there if we look for it, so just return early here.
2509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return True
2510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        else:
2511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          # Got some other operator.
2512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return False
2513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
2515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Expecting opening parenthesis or opening bracket
2516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if operator in ('>', ')', ']'):
2517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.append(operator)
2518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        elif operator in ('(', '['):
2519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          nesting_stack.pop()
2520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2521ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
2522ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Scan the previous line
2523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum -= 1
2524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if linenum < 0:
2525ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        break
2526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line = clean_lines.elided[linenum]
2527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Exhausted all earlier lines and still no matching angle bracket.
2529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return False
2530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
2533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for the correctness of various spacing issues in the code.
2534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Things we check for: spaces around operators, spaces after
2536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if/for/while/switch, no spaces around parens in function calls, two
2537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  spaces between code and comment, don't start a block with a blank
2538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line, don't end a function with a blank line, don't add a blank line
2539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  after public/protected/private, don't have too many blank lines in a row.
2540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nesting_state: A _NestingState instance which maintains information about
2546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the current stack of nested blocks being parsed.
2547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2550b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Don't use "elided" lines here, otherwise we can't check commented lines.
2551b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Don't want to use "raw" either, because we don't want to check inside C++11
2552b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # raw strings,
2553b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  raw = clean_lines.lines_without_raw_strings
2554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = raw[linenum]
2555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Before nixing comments, check if the line is blank for no good
2557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # reason.  This includes the first line after a block is opened, and
2558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # blank lines at the end of a function (ie, right before a line like '}'
2559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Skip all the blank line checks if we are immediately inside a
2561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # namespace body.  In other words, don't issue blank line warnings
2562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # for this block:
2563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   namespace {
2564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   }
2566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # A warning about missing end of namespace comments will be issued instead.
2568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if IsBlankLine(line) and not nesting_state.InNamespaceBody():
2569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elided = clean_lines.elided
2570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prev_line = elided[linenum - 1]
2571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prevbrace = prev_line.rfind('{')
2572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # TODO(unknown): Don't complain if line before blank line, and line after,
2573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                both start with alnums and are indented the same amount.
2574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                This ignores whitespace at the start of a namespace block
2575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                because those are not usually indented.
2576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
2577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # OK, we have a blank line at the start of a code block.  Before we
2578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # complain, we check if it is an exception to the rule: The previous
2579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # non-empty line has the parameters of a function header that are indented
2580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 4 spaces (because they did not fit in a 80 column line when placed on
2581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # the same line as the function name).  We also check for the case where
2582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # the previous line is indented 6 spaces, which may happen when the
2583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # initializers of a constructor do not fit into a 80 column line.
2584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      exception = False
2585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r' {6}\w', prev_line):  # Initializer list?
2586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # We are looking for the opening column of initializer list, which
2587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # should be indented 4 spaces to cause 6 space indentation afterwards.
2588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        search_position = linenum-2
2589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        while (search_position >= 0
2590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               and Match(r' {6}\w', elided[search_position])):
2591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          search_position -= 1
2592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        exception = (search_position >= 0
2593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     and elided[search_position][:5] == '    :')
2594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      else:
2595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # Search for the function arguments or an initializer list.  We use a
2596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # simple heuristic here: If the line is indented 4 spaces; and we have a
2597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # closing paren, without the opening paren, followed by an opening brace
2598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # or colon (for initializer lists) we assume that it is the last line of
2599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # a function header.  If we have a colon indented 4 spaces, it is an
2600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # initializer list.
2601ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
2602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           prev_line)
2603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     or Match(r' {4}:', prev_line))
2604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2605ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not exception:
2606ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/blank_line', 2,
2607b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Redundant blank line at the start of a code block '
2608b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'should be deleted.')
2609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Ignore blank lines at the end of a block in a long if-else
2610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # chain, like this:
2611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   if (condition1) {
2612ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #     // Something followed by a blank line
2613ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #
2614ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   } else if (condition2) {
2615ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #     // Something else
2616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #   }
2617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if linenum + 1 < clean_lines.NumLines():
2618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      next_line = raw[linenum + 1]
2619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (next_line
2620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          and Match(r'\s*}', next_line)
2621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          and next_line.find('} else ') == -1):
2622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/blank_line', 3,
2623b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Redundant blank line at the end of a code block '
2624b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'should be deleted.')
2625ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    matched = Match(r'\s*(public|protected|private):', prev_line)
2627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if matched:
2628ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/blank_line', 3,
2629ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Do not leave a blank line after "%s:"' % matched.group(1))
2630ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2631ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Next, we complain if there's a comment too near the text
2632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  commentpos = line.find('//')
2633ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if commentpos != -1:
2634ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Check if the // may be in quotes.  If so, ignore it
2635b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
2636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (line.count('"', 0, commentpos) -
2637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        line.count('\\"', 0, commentpos)) % 2 == 0:   # not in quotes
2638ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Allow one space for new scopes, two spaces otherwise:
2639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if (not Match(r'^\s*{ //', line) and
2640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ((commentpos >= 1 and
2641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            line[commentpos-1] not in string.whitespace) or
2642ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           (commentpos >= 2 and
2643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            line[commentpos-2] not in string.whitespace))):
2644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/comments', 2,
2645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'At least two spaces is best between code and comments')
2646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # There should always be a space between the // and the comment
2647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      commentend = commentpos + 2
2648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if commentend < len(line) and not line[commentend] == ' ':
2649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # but some lines are exceptions -- e.g. if they're big
2650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # comment delimiters like:
2651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # //----------------------------------------------------------
2652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # or are an empty C++ style Doxygen comment, like:
2653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # ///
2654b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # or C++ style Doxygen comments placed after the variable:
2655b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # ///<  Header comment
2656b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # //!<  Header comment
2657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # or they begin with multiple slashes followed by a space:
2658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        # //////// Header comment
2659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
2660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 Search(r'^/$', line[commentend:]) or
2661b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                 Search(r'^!< ', line[commentend:]) or
2662b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                 Search(r'^/< ', line[commentend:]) or
2663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 Search(r'^/+ ', line[commentend:]))
2664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if not match:
2665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          error(filename, linenum, 'whitespace/comments', 4,
2666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                'Should have a space between // and comment')
2667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      CheckComment(line[commentpos:], filename, linenum, error)
2668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]  # get rid of comments and strings
2670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Don't try to do spacing checks for operator methods
2672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
2673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
2675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Otherwise not.  Note we only check for non-spaces on *both* sides;
2676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # sometimes people put non-spaces on one side when aligning ='s among
2677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # many lines (not that this is behavior that I approve of...)
2678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line):
2679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/operators', 4,
2680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing spaces around =')
2681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2682ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # It's ok not to have spaces around binary operators like + - * /, but if
2683ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # there's too little whitespace, we get concerned.  It's hard to tell,
2684ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # though, so we punt on this one for now.  TODO.
2685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # You should always have whitespace around binary operators.
2687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check <= and >= first to avoid false positives with < and >, then
2689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # check non-include lines for spacing around < and >.
2690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
2691ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/operators', 3,
2693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing spaces around %s' % match.group(1))
2694ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We allow no-spaces around << when used like this: 10<<20, but
2695ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # not otherwise (particularly, not when used as streams)
2696b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Also ignore using ns::operator<<;
2697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  match = Search(r'(operator|\S)(?:L|UL|ULL|l|ul|ull)?<<(\S)', line)
2698b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (match and
2699b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not (match.group(1).isdigit() and match.group(2).isdigit()) and
2700b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not (match.group(1) == 'operator' and match.group(2) == ';')):
2701ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/operators', 3,
2702ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing spaces around <<')
2703ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif not Match(r'#.*include', line):
2704ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Avoid false positives on ->
2705ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    reduced_line = line.replace('->', '')
2706ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2707ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Look for < that is not surrounded by spaces.  This is only
2708ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # triggered if both sides are missing spaces, even though
2709ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # technically should should flag if at least one side is missing a
2710ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # space.  This is done to avoid some false positives with shifts.
2711ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(r'[^\s<]<([^\s=<].*)', reduced_line)
2712ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (match and
2713ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not FindNextMatchingAngleBracket(clean_lines, linenum, match.group(1))):
2714ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/operators', 3,
2715ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Missing spaces around <')
2716ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2717ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Look for > that is not surrounded by spaces.  Similar to the
2718ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # above, we only trigger if both sides are missing spaces to avoid
2719ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # false positives with shifts.
2720ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(r'^(.*[^\s>])>[^\s=>]', reduced_line)
2721ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (match and
2722ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not FindPreviousMatchingAngleBracket(clean_lines, linenum,
2723ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                             match.group(1))):
2724ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/operators', 3,
2725ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Missing spaces around >')
2726ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2727ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We allow no-spaces around >> for almost anything.  This is because
2728ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # C++11 allows ">>" to close nested templates, which accounts for
2729ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # most cases when ">>" is not followed by a space.
2730ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2731ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We still warn on ">>" followed by alpha character, because that is
2732ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # likely due to ">>" being used for right shifts, e.g.:
2733ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   value >> alpha
2734ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2735ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # When ">>" is used to close templates, the alphanumeric letter that
2736ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # follows would be part of an identifier, and there should still be
2737ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # a space separating the template type and the identifier.
2738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   type<type<type>> alpha
2739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'>>[a-zA-Z_]', line)
2740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/operators', 3,
2742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing spaces around >>')
2743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # There shouldn't be space around unary operators
2745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
2746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/operators', 4,
2748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Extra space for operator %s' % match.group(1))
2749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # A pet peeve of mine: no spaces after an if, while, switch, or for
2751ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r' (if\(|for\(|while\(|switch\()', line)
2752ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2753ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/parens', 5,
2754ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing space before ( in %s' % match.group(1))
2755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # For if/for/while/switch, the left and right parens should be
2757ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # consistent about how many spaces are inside the parens, and
2758ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # there should either be zero or one spaces inside the parens.
2759ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We don't want: "if ( foo)" or "if ( foo   )".
2760ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
2761ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'\b(if|for|while|switch)\s*'
2762ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
2763ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 line)
2764ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
2765ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if len(match.group(2)) != len(match.group(4)):
2766ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not (match.group(3) == ';' and
2767ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              len(match.group(2)) == 1 + len(match.group(4)) or
2768ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
2769ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/parens', 5,
2770ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Mismatching spaces inside () in %s' % match.group(1))
2771b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if len(match.group(2)) not in [0, 1]:
2772ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/parens', 5,
2773ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Should have zero or one spaces inside ( and ) in %s' %
2774ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            match.group(1))
2775ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2776ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # You should always have a space after a comma (either as fn arg or operator)
2777b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
2778b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # This does not apply when the non-space character following the
2779b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # comma is another comma, since the only time when that happens is
2780b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # for empty macro arguments.
2781b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
2782b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # We run this check in two passes: first pass on elided lines to
2783b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # verify that lines contain missing whitespaces, second pass on raw
2784b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # lines to confirm that those missing whitespaces are not due to
2785b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # elided comments.
2786b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Search(r',[^,\s]', line) and Search(r',[^,\s]', raw[linenum]):
2787ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/comma', 3,
2788ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing space after ,')
2789ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2790ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # You should always have a space after a semicolon
2791ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # except for few corner cases
2792ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
2793ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # space after ;
2794ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r';[^\s};\\)/]', line):
2795ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/semicolon', 3,
2796ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing space after ;')
2797ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2798ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Next we will look for issues with function calls.
2799ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckSpacingForFunctionCall(filename, line, linenum, error)
2800ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2801ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Except after an opening paren, or after another opening brace (in case of
2802ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # an initializer list, for instance), you should have spaces before your
2803ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # braces. And since you should never have braces at the beginning of a line,
2804ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # this is an easy test.
2805b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  match = Match(r'^(.*[^ ({]){', line)
2806b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if match:
2807b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Try a bit harder to check for brace initialization.  This
2808b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # happens in one of the following forms:
2809b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Constructor() : initializer_list_{} { ... }
2810b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Constructor{}.MemberFunction()
2811b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Type variable{};
2812b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   FunctionCall(type{}, ...);
2813b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   LastArgument(..., type{});
2814b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   LOG(INFO) << type{} << " ...";
2815b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   map_of_type[{...}] = ...;
2816b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
2817b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # We check for the character following the closing brace, and
2818b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # silence the warning if it's one of those listed above, i.e.
2819b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # "{.;,)<]".
2820b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
2821b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # To account for nested initializer list, we allow any number of
2822b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # closing braces up to "{;,)<".  We can't simply silence the
2823b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # warning on first sight of closing brace, because that would
2824b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # cause false negatives for things that are not initializer lists.
2825b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Silence this:         But not this:
2826b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #     Outer{                if (...) {
2827b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #       Inner{...}            if (...){  // Missing space before {
2828b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #     };                    }
2829b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
2830b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # There is a false negative with this approach if people inserted
2831b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # spurious semicolons, e.g. "if (cond){};", but we will catch the
2832b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # spurious semicolon with a separate check.
2833b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (endline, endlinenum, endpos) = CloseExpression(
2834b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        clean_lines, linenum, len(match.group(1)))
2835b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    trailing_text = ''
2836b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if endpos > -1:
2837b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      trailing_text = endline[endpos:]
2838b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    for offset in xrange(endlinenum + 1,
2839b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                         min(endlinenum + 3, clean_lines.NumLines() - 1)):
2840b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      trailing_text += clean_lines.elided[offset]
2841b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if not Match(r'^[\s}]*[{.;,)<\]]', trailing_text):
2842b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      error(filename, linenum, 'whitespace/braces', 5,
2843b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            'Missing space before {')
2844ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2845ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Make sure '} else {' has spaces.
2846ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'}else', line):
2847ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/braces', 5,
2848ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing space before else')
2849ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2850ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # You shouldn't have spaces before your brackets, except maybe after
2851ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # 'delete []' or 'new char * []'.
2852ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line):
2853ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/braces', 5,
2854ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Extra space before [')
2855ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2856ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # You shouldn't have a space before a semicolon at the end of the line.
2857ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # There's a special case for "for" since the style guide allows space before
2858ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # the semicolon there.
2859ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r':\s*;\s*$', line):
2860ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/semicolon', 5,
2861ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Semicolon defining empty statement. Use {} instead.')
2862ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif Search(r'^\s*;\s*$', line):
2863ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/semicolon', 5,
2864ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Line contains only semicolon. If this should be an empty statement, '
2865ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'use {} instead.')
2866ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif (Search(r'\s+;\s*$', line) and
2867ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Search(r'\bfor\b', line)):
2868ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/semicolon', 5,
2869ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Extra space before last semicolon. If this should be an empty '
2870ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'statement, use {} instead.')
2871ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2872ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # In range-based for, we wanted spaces before and after the colon, but
2873ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # not around "::" tokens that might appear.
2874ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (Search('for *\(.*[^:]:[^: ]', line) or
2875ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Search('for *\(.*[^: ]:[^:]', line)):
2876ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/forcolon', 2,
2877ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Missing space around colon in range-based for loop')
2878ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2879ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2880ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
2881ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for additional blank line issues related to sections.
2882ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2883ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Currently the only thing checked here is blank line before protected/private.
2884ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2885ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2886ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2887ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2888ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    class_info: A _ClassInfo objects.
2889ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2890ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2891ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2892ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Skip checks if the class is small, where small means 25 lines or less.
2893ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # 25 lines seems like a good cutoff since that's the usual height of
2894ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # terminals, and any class that can't fit in one screen can't really
2895ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # be considered "small".
2896ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2897ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Also skip checks if we are on the first line.  This accounts for
2898ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # classes that look like
2899ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   class Foo { public: ... };
2900ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
2901ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If we didn't find the end of the class, last_line would be zero,
2902ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # and the check will be skipped by the first condition.
2903ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (class_info.last_line - class_info.starting_linenum <= 24 or
2904ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      linenum <= class_info.starting_linenum):
2905ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
2906ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2907ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
2908ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if matched:
2909ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Issue warning if the line before public/protected/private was
2910ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # not a blank line, but don't do this if the previous line contains
2911ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # "class" or "struct".  This can happen two ways:
2912ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #  - We are at the beginning of the class.
2913ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #  - We are forward-declaring an inner class that is semantically
2914ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #    private, but needed to be public for implementation reasons.
2915ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Also ignores cases where the previous line ends with a backslash as can be
2916ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # common when defining classes in C macros.
2917ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prev_line = clean_lines.lines[linenum - 1]
2918ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (not IsBlankLine(prev_line) and
2919ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Search(r'\b(class|struct)\b', prev_line) and
2920ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Search(r'\\$', prev_line)):
2921ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Try a bit harder to find the beginning of the class.  This is to
2922ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # account for multi-line base-specifier lists, e.g.:
2923ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #   class Derived
2924ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #       : public Base {
2925ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      end_class_head = class_info.starting_linenum
2926ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for i in range(class_info.starting_linenum, linenum):
2927ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if Search(r'\{\s*$', clean_lines.lines[i]):
2928ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          end_class_head = i
2929ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          break
2930ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if end_class_head < linenum - 1:
2931ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'whitespace/blank_line', 3,
2932ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              '"%s:" should be preceded by a blank line' % matched.group(1))
2933ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2934ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2935ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef GetPreviousNonBlankLine(clean_lines, linenum):
2936ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Return the most recent non-blank line and its line number.
2937ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2938ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2939ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file contents.
2940ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2941ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2942ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
2943ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    A tuple with two elements.  The first element is the contents of the last
2944ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    non-blank line before the current line, or the empty string if this is the
2945ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    first non-blank line.  The second is the line number of that line, or -1
2946ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if this is the first non-blank line.
2947ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2948ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2949ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  prevlinenum = linenum - 1
2950ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while prevlinenum >= 0:
2951ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prevline = clean_lines.elided[prevlinenum]
2952ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not IsBlankLine(prevline):     # if not a blank line...
2953ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return (prevline, prevlinenum)
2954ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prevlinenum -= 1
2955ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return ('', -1)
2956ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2957ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2958ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckBraces(filename, clean_lines, linenum, error):
2959ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Looks for misplaced braces (e.g. at the end of line).
2960ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2961ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
2962ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
2963ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
2964ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
2965ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
2966ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
2967ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2968ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]        # get rid of comments and strings
2969ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2970ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'\s*{\s*$', line):
2971b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # We allow an open brace to start a line in the case where someone is using
2972b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # braces in a block to explicitly create a new scope, which is commonly used
2973b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # to control the lifetime of stack-allocated variables.  Braces are also
2974b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # used for brace initializers inside function calls.  We don't detect this
2975b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # perfectly: we just don't complain if the last non-whitespace character on
2976b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
2977b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # previous line starts a preprocessor block.
2978ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
2979b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (not Search(r'[,;:}{(]\s*$', prevline) and
2980ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Match(r'\s*#', prevline)):
2981ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/braces', 4,
2982ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '{ should almost always be at the end of the previous line')
2983ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2984ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # An else clause should be on the same line as the preceding closing brace.
2985ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'\s*else\s*', line):
2986ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
2987ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Match(r'\s*}\s*$', prevline):
2988ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/newline', 4,
2989ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'An else should appear on the same line as the preceding }')
2990ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2991ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If braces come on one side of an else, they should be on both.
2992ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # However, we have to worry about "else if" that spans multiple lines!
2993ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
2994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Search(r'}\s*else if([^{]*)$', line):       # could be multi-line if
2995ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # find the ( after the if
2996ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      pos = line.find('else if')
2997ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      pos = line.find('(', pos)
2998ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if pos > 0:
2999ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
3000ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if endline[endpos:].find('{') == -1:    # must be brace after if
3001ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          error(filename, linenum, 'readability/braces', 5,
3002ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                'If an else has a brace on one side, it should have it on both')
3003ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:            # common case: else not followed by a multi-line if
3004ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/braces', 5,
3005ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'If an else has a brace on one side, it should have it on both')
3006ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3007ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Likewise, an else should never have the else clause on the same line
3008ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
3009ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/newline', 4,
3010ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Else clause should never be on same line as else (use 2 lines)')
3011ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3012ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # In the same way, a do/while should never be on one line
3013ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'\s*do [^\s{]', line):
3014ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/newline', 4,
3015ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'do/while clauses should not be on a single line')
3016ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3017b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Block bodies should not be followed by a semicolon.  Due to C++11
3018b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # brace initialization, there are more places where semicolons are
3019b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # required than not, so we use a whitelist approach to check these
3020b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # rather than a blacklist.  These are the places where "};" should
3021b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # be replaced by just "}":
3022b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 1. Some flavor of block following closing parenthesis:
3023b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    for (;;) {};
3024b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    while (...) {};
3025b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    switch (...) {};
3026b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    Function(...) {};
3027b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    if (...) {};
3028b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    if (...) else if (...) {};
3029b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3030b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 2. else block:
3031b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    if (...) else {};
3032b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3033b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 3. const member function:
3034b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    Function(...) const {};
3035b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3036b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 4. Block following some statement:
3037b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    x = 42;
3038b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    {};
3039b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3040b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 5. Block at the beginning of a function:
3041b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    Function(...) {
3042b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #      {};
3043b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    }
3044b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3045b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    Note that naively checking for the preceding "{" will also match
3046b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    braces inside multi-dimensional arrays, but this is fine since
3047b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    that expression will not contain semicolons.
3048b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3049b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 6. Block following another block:
3050b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    while (true) {}
3051b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    {};
3052b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3053b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # 7. End of namespaces:
3054b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    namespace {};
3055b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3056b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    These semicolons seems far more common than other kinds of
3057b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    redundant semicolons, possibly due to people converting classes
3058b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #    to namespaces.  For now we do not warn for this case.
3059b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3060b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Try matching case 1 first.
3061b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  match = Match(r'^(.*\)\s*)\{', line)
3062b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if match:
3063b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Matched closing parenthesis (case 1).  Check the token before the
3064b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # matching opening parenthesis, and don't warn if it looks like a
3065b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # macro.  This avoids these false positives:
3066b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - macro that defines a base class
3067b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - multi-line macro that defines a base class
3068b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - macro that defines the whole class-head
3069b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3070b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # But we still issue warnings for macros that we know are safe to
3071b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # warn, specifically:
3072b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
3073b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - TYPED_TEST
3074b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - INTERFACE_DEF
3075b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
3076b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3077b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # We implement a whitelist of safe macros instead of a blacklist of
3078b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # unsafe macros, even though the latter appears less frequently in
3079b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # google code and would have been easier to implement.  This is because
3080b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # the downside for getting the whitelist wrong means some extra
3081b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # semicolons, while the downside for getting the blacklist wrong
3082b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # would result in compile errors.
3083b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3084b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # In addition to macros, we also don't want to warn on compound
3085b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # literals.
3086b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    closing_brace_pos = match.group(1).rfind(')')
3087b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    opening_parenthesis = ReverseCloseExpression(
3088b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        clean_lines, linenum, closing_brace_pos)
3089b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if opening_parenthesis[2] > -1:
3090b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
3091b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
3092b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if ((macro and
3093b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian           macro.group(1) not in (
3094b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian               'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
3095b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian               'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
3096b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian               'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
3097b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          Search(r'\s+=\s*$', line_prefix)):
3098b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        match = None
3099b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3100b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  else:
3101b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Try matching cases 2-3.
3102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
3103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if not match:
3104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Try matching cases 4-6.  These are always matched on separate lines.
3105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #
3106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Note that we can't simply concatenate the previous line to the
3107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # current line and do a single match, otherwise we may output
3108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # duplicate warnings for the blank line case:
3109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #   if (cond) {
3110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #     // blank line
3111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #   }
3112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if prevline and Search(r'[;{}]\s*$', prevline):
3114b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        match = Match(r'^(\s*)\{', line)
3115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3116b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Check matching closing brace
3117b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if match:
3118b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (endline, endlinenum, endpos) = CloseExpression(
3119b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        clean_lines, linenum, len(match.group(1)))
3120b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
3121b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Current {} pair is eligible for semicolon check, and we have found
3122b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # the redundant semicolon, output warning here.
3123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #
3124b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Note: because we are scanning forward for opening braces, and
3125b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # outputting warnings for the matching closing brace, if there are
3126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # nested blocks with trailing semicolons, we will get the error
3127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # messages in reversed order.
3128b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      error(filename, endlinenum, 'readability/braces', 4,
3129b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            "You don't need a ; after a }")
3130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3132b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CheckEmptyBlockBody(filename, clean_lines, linenum, error):
3133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Look for empty loop/conditional body with only a single semicolon.
3134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Search for loop keywords at the beginning of the line.  Because only
3143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # whitespaces are allowed before the keywords, this will also ignore most
3144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # do-while-loops, since those lines should start with closing brace.
3145b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3146b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # We also check "if" blocks here, since an empty conditional block
3147b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # is likely an error.
3148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
3149b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  matched = Match(r'\s*(for|while|if)\s*\(', line)
3150b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if matched:
3151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Find the end of the conditional expression
3152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    (end_line, end_linenum, end_pos) = CloseExpression(
3153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        clean_lines, linenum, line.find('('))
3154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Output warning if what follows the condition expression is a semicolon.
3156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # No warning for all other cases, including whitespace or newline, since we
3157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # have a separate check for semicolons preceded by whitespace.
3158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if end_pos >= 0 and Match(r';', end_line[end_pos:]):
3159b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if matched.group(1) == 'if':
3160b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
3161b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Empty conditional bodies should use {}')
3162b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      else:
3163b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
3164b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Empty loop bodies should use {} or continue')
3165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckCheck(filename, clean_lines, linenum, error):
3168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks the use of CHECK and EXPECT macros.
3169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3174ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Decide the set of replacement macros that should be suggested
3178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  lines = clean_lines.elided
3179b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  check_macro = None
3180b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  start_pos = -1
3181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for macro in _CHECK_MACROS:
3182b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    i = lines[linenum].find(macro)
3183b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if i >= 0:
3184b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      check_macro = macro
3185b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3186b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Find opening parenthesis.  Do a regular expression match here
3187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # to make sure that we are matching the expected CHECK macro, as
3188b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # opposed to some other macro that happens to contain the CHECK
3189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # substring.
3190b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      matched = Match(r'^(.*\b' + check_macro + r'\s*)\(', lines[linenum])
3191b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if not matched:
3192b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        continue
3193b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      start_pos = len(matched.group(1))
3194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break
3195b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if not check_macro or start_pos < 0:
3196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT'
3197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
3198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Find end of the boolean expression by matching parentheses
3200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  (last_line, end_line, end_pos) = CloseExpression(
3201b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      clean_lines, linenum, start_pos)
3202b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if end_pos < 0:
3203b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return
3204b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if linenum == end_line:
3205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    expression = lines[linenum][start_pos + 1:end_pos - 1]
3206b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  else:
3207b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    expression = lines[linenum][start_pos + 1:]
3208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    for i in xrange(linenum + 1, end_line):
3209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      expression += lines[i]
3210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    expression += last_line[0:end_pos - 1]
3211b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Parse expression so that we can take parentheses into account.
3213b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # This avoids false positives for inputs like "CHECK((a < 4) == b)",
3214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # which is not replaceable by CHECK_LE.
3215b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  lhs = ''
3216b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  rhs = ''
3217b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  operator = None
3218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while expression:
3219b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
3220b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                    r'==|!=|>=|>|<=|<|\()(.*)$', expression)
3221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if matched:
3222b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      token = matched.group(1)
3223b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if token == '(':
3224b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Parenthesized operand
3225b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        expression = matched.group(2)
3226b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        (end, _) = FindEndOfExpressionInLine(expression, 0, 1, '(', ')')
3227b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if end < 0:
3228b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          return  # Unmatched parenthesis
3229b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        lhs += '(' + expression[0:end]
3230b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        expression = expression[end:]
3231b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      elif token in ('&&', '||'):
3232b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Logical and/or operators.  This means the expression
3233b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # contains more than one term, for example:
3234b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        #   CHECK(42 < a && a < b);
3235b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        #
3236b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # These are not replaceable with CHECK_LE, so bail out early.
3237b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return
3238b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
3239b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Non-relational operator
3240b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        lhs += token
3241b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        expression = matched.group(2)
3242b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      else:
3243b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        # Relational operator
3244b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        operator = token
3245b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        rhs = matched.group(2)
3246b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        break
3247b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    else:
3248b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Unparenthesized operand.  Instead of appending to lhs one character
3249b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # at a time, we do another regular expression match to consume several
3250b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # characters at once if possible.  Trivial benchmark shows that this
3251b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # is more efficient when the operands are longer than a single
3252b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # character, which is generally the case.
3253b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
3254b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if not matched:
3255b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        matched = Match(r'^(\s*\S)(.*)$', expression)
3256b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if not matched:
3257b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          break
3258b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      lhs += matched.group(1)
3259b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      expression = matched.group(2)
3260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3261b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Only apply checks if we got all parts of the boolean expression
3262b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if not (lhs and operator and rhs):
3263b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return
3264b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3265b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Check that rhs do not contain logical operators.  We already know
3266b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # that lhs is fine since the loop above parses out && and ||.
3267b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if rhs.find('&&') > -1 or rhs.find('||') > -1:
3268b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return
3269b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3270b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # At least one of the operands must be a constant literal.  This is
3271b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # to avoid suggesting replacements for unprintable things like
3272b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # CHECK(variable != iterator)
3273b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3274b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # The following pattern matches decimal, hex integers, strings, and
3275b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # characters (in that order).
3276b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  lhs = lhs.strip()
3277b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  rhs = rhs.strip()
3278b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
3279b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Match(match_constant, lhs) or Match(match_constant, rhs):
3280b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Note: since we know both lhs and rhs, we can provide a more
3281b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # descriptive error message like:
3282b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
3283b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Instead of:
3284b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #   Consider using CHECK_EQ instead of CHECK(a == b)
3285b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # We are still keeping the less descriptive message because if lhs
3287b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # or rhs gets long, the error message might become unreadable.
3288b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    error(filename, linenum, 'readability/check', 2,
3289b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'Consider using %s instead of %s(a %s b)' % (
3290b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              _CHECK_REPLACEMENT[check_macro][operator],
3291b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              check_macro, operator))
3292ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3293ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3294ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckAltTokens(filename, clean_lines, linenum, error):
3295ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Check alternative keywords being used in boolean expressions.
3296ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3297ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3298ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3299ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3300ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3301ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3302ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3303ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
3304ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3305ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Avoid preprocessor lines
3306ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Match(r'^\s*#', line):
3307ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
3308ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3309ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Last ditch effort to avoid multi-line comments.  This will not help
3310ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if the comment started before the current line or ended after the
3311ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # current line, but it catches most of the false positives.  At least,
3312ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # it provides a way to workaround this warning for people who use
3313ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # multi-line comments in preprocessor macros.
3314ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
3315ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(unknown): remove this once cpplint has better support for
3316ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # multi-line comments.
3317ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if line.find('/*') >= 0 or line.find('*/') >= 0:
3318ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
3319ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3320ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
3321ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'readability/alt_tokens', 2,
3322ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Use operator %s instead of %s' % (
3323ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
3324ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3325ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3326ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef GetLineWidth(line):
3327ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Determines the width of the line in column positions.
3328ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3329ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3330ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: A string, which may be a Unicode string.
3331ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3332ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
3333ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The width of the line in column positions, accounting for Unicode
3334ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    combining characters and wide characters.
3335ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3336ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if isinstance(line, unicode):
3337ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    width = 0
3338ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for uc in unicodedata.normalize('NFC', line):
3339ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if unicodedata.east_asian_width(uc) in ('W', 'F'):
3340ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        width += 2
3341ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      elif not unicodedata.combining(uc):
3342ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        width += 1
3343ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return width
3344ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
3345ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return len(line)
3346ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3347ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3348ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
3349ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang               error):
3350ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks rules from the 'C++ style rules' section of cppguide.html.
3351ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Most of these rules are hard to test (naming, comment style), but we
3353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  do what we can.  In particular we check for 2-space indents, line lengths,
3354ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  tab usage, spaces inside code, etc.
3355ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3356ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3357ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3358ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3360ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    file_extension: The extension (without the dot) of the filename.
3361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nesting_state: A _NestingState instance which maintains information about
3362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the current stack of nested blocks being parsed.
3363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3366b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Don't use "elided" lines here, otherwise we can't check commented lines.
3367b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Don't want to use "raw" either, because we don't want to check inside C++11
3368b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # raw strings,
3369b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  raw_lines = clean_lines.lines_without_raw_strings
3370ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = raw_lines[linenum]
3371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if line.find('\t') != -1:
3373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/tab', 1,
3374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Tab found; better to use spaces')
3375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # One or three blank spaces at the beginning of the line is weird; it's
3377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # hard to reconcile that with 2-space indents.
3378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # NOTE: here are the conditions rob pike used for his tests.  Mine aren't
3379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # as sophisticated, but it may be worth becoming so:  RLENGTH==initial_spaces
3380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(RLENGTH > 20) complain = 0;
3381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match($0, " +(error|private|public|protected):")) complain = 0;
3382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match(prev, "&& *$")) complain = 0;
3383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match(prev, "\\|\\| *$")) complain = 0;
3384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match(prev, "[\",=><] *$")) complain = 0;
3385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match($0, " <<")) complain = 0;
3386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(match(prev, " +for \\(")) complain = 0;
3387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
3388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  initial_spaces = 0
3389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  cleansed_line = clean_lines.elided[linenum]
3390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while initial_spaces < len(line) and line[initial_spaces] == ' ':
3391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    initial_spaces += 1
3392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if line and line[-1].isspace():
3393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/end_of_line', 4,
3394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Line ends in whitespace.  Consider deleting these extra spaces.')
3395b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # There are certain situations we allow one space, notably for section labels
3396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif ((initial_spaces == 1 or initial_spaces == 3) and
3397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
3398ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/indent', 3,
3399ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Weird number of spaces at line-start.  '
3400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Are you using a 2-space indent?')
3401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check if the line is a header guard.
3403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  is_header_guard = False
3404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if file_extension == 'h':
3405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    cppvar = GetHeaderGuardCPPVariable(filename)
3406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (line.startswith('#ifndef %s' % cppvar) or
3407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        line.startswith('#define %s' % cppvar) or
3408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        line.startswith('#endif  // %s' % cppvar)):
3409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      is_header_guard = True
3410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # #include lines and header guards can be long, since there's no clean way to
3411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # split them.
3412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
3413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # URLs can be long too.  It's possible to split these, but it makes them
3414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # harder to cut&paste.
3415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
3416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The "$Id:...$" comment may also get very long without it being the
3417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # developers fault.
3418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (not line.startswith('#include') and not is_header_guard and
3419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      not Match(r'^\s*//.*http(s?)://\S*$', line) and
3420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
3421ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line_width = GetLineWidth(line)
3422b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    extended_length = int((_line_length * 1.25))
3423b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if line_width > extended_length:
3424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/line_length', 4,
3425b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            'Lines should very rarely be longer than %i characters' %
3426b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            extended_length)
3427b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif line_width > _line_length:
3428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'whitespace/line_length', 2,
3429b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            'Lines should be <= %i characters long' % _line_length)
3430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (cleansed_line.count(';') > 1 and
3432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # for loops are allowed two ;'s (and may run over two lines).
3433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      cleansed_line.find('for') == -1 and
3434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
3435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
3436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # It's ok to have many commands in a switch case that fits in 1 line
3437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      not ((cleansed_line.find('case ') != -1 or
3438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            cleansed_line.find('default:') != -1) and
3439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           cleansed_line.find('break;') != -1)):
3440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'whitespace/newline', 0,
3441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'More than one command on the same line')
3442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Some more style checks
3444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckBraces(filename, clean_lines, linenum, error)
3445b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  CheckEmptyBlockBody(filename, clean_lines, linenum, error)
3446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckAccess(filename, clean_lines, linenum, nesting_state, error)
3447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
3448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckCheck(filename, clean_lines, linenum, error)
3449ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckAltTokens(filename, clean_lines, linenum, error)
3450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  classinfo = nesting_state.InnermostClass()
3451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if classinfo:
3452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
3453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
3456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
3457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang# Matches the first component of a filename delimited by -s and _s. That is:
3458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
3459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#  _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
3460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#  _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
3461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#  _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
3462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
3463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _DropCommonSuffixes(filename):
3466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Drops common suffixes like _test.cc or -inl.h from filename.
3467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  For example:
3469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _DropCommonSuffixes('foo/foo-inl.h')
3470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'foo/foo'
3471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _DropCommonSuffixes('foo/bar/foo.cc')
3472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'foo/bar/foo'
3473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _DropCommonSuffixes('foo/foo_internal.h')
3474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'foo/foo'
3475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
3476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    'foo/foo_unusualinternal'
3477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The input filename.
3480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
3482ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The filename with the common suffix removed.
3483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
3485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 'inl.h', 'impl.h', 'internal.h'):
3486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (filename.endswith(suffix) and len(filename) > len(suffix) and
3487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        filename[-len(suffix) - 1] in ('-', '_')):
3488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return filename[:-len(suffix) - 1]
3489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return os.path.splitext(filename)[0]
3490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _IsTestFilename(filename):
3493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Determines if the given filename has a suffix that identifies it as a test.
3494ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The input filename.
3497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
3499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True if 'filename' looks like a test, False otherwise.
3500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (filename.endswith('_test.cc') or
3502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename.endswith('_unittest.cc') or
3503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filename.endswith('_regtest.cc')):
3504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return True
3505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
3506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
3507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _ClassifyInclude(fileinfo, include, is_system):
3510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Figures out what kind of header 'include' is.
3511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    fileinfo: The current file cpplint is running over. A FileInfo instance.
3514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include: The path to a #included file.
3515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    is_system: True if the #include used <> rather than "".
3516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
3518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    One of the _XXX_HEADER constants.
3519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  For example:
3521ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
3522ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _C_SYS_HEADER
3523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
3524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _CPP_SYS_HEADER
3525ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
3526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _LIKELY_MY_HEADER
3527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
3528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ...                  'bar/foo_other_ext.h', False)
3529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _POSSIBLE_MY_HEADER
3530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
3531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _OTHER_HEADER
3532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # This is a list of all standard c++ header files, except
3534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # those already checked for above.
3535b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  is_cpp_h = include in _CPP_HEADERS
3536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if is_system:
3538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if is_cpp_h:
3539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return _CPP_SYS_HEADER
3540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
3541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return _C_SYS_HEADER
3542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If the target file and the include we're checking share a
3544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # basename when we drop common extensions, and the include
3545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # lives in . , then it's likely to be owned by the target file.
3546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  target_dir, target_base = (
3547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
3548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
3549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if target_base == include_base and (
3550ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include_dir == target_dir or
3551ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include_dir == os.path.normpath(target_dir + '/../public')):
3552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return _LIKELY_MY_HEADER
3553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If the target and include share some initial basename
3555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # component, it's possible the target is implementing the
3556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # include, so it's allowed to be first, but we'll never
3557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # complain if it's not there.
3558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  target_first_component = _RE_FIRST_COMPONENT.match(target_base)
3559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  include_first_component = _RE_FIRST_COMPONENT.match(include_base)
3560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (target_first_component and include_first_component and
3561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      target_first_component.group(0) ==
3562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include_first_component.group(0)):
3563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return _POSSIBLE_MY_HEADER
3564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return _OTHER_HEADER
3566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3567ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
3570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Check rules that are applicable to #include lines.
3571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Strings on #include lines are NOT removed from elided line, to make
3573ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  certain tasks easier. However, to prevent false positives, checks
3574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  applicable to #include lines in CheckLanguage must be put here.
3575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include_state: An _IncludeState instance in which the headers are inserted.
3581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  fileinfo = FileInfo(filename)
3584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.lines[linenum]
3586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # "include" should use the new style "foo/bar.h" instead of just "bar.h"
3588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
3589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/include', 4,
3590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Include the directory when naming .h files')
3591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # we shouldn't include a file more than once. actually, there are a
3593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # handful of instances where doing so is okay, but in general it's
3594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # not.
3595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = _RE_PATTERN_INCLUDE.search(line)
3596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
3597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include = match.group(2)
3598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    is_system = (match.group(1) == '<')
3599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if include in include_state:
3600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'build/include', 4,
3601ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            '"%s" already included at %s:%s' %
3602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            (include, filename, include_state[include]))
3603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
3604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include_state[include] = linenum
3605ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3606ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # We want to ensure that headers appear in the right order:
3607ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 1) for foo.cc, foo.h  (preferred location)
3608ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 2) c system files
3609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 3) cpp system files
3610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 4) for foo.cc, foo.h  (deprecated location)
3611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 5) other google headers
3612ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      #
3613ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # We classify each include statement as one of those 5 types
3614ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # using a number of techniques. The include_state object keeps
3615ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # track of the highest type seen, and complains if we see a
3616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # lower type after that.
3617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error_message = include_state.CheckNextIncludeOrder(
3618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          _ClassifyInclude(fileinfo, include, is_system))
3619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if error_message:
3620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'build/include_order', 4,
3621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              '%s. Should be: %s.h, c system, c++ system, other.' %
3622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              (error_message, fileinfo.BaseName()))
3623b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
3624b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if not include_state.IsInAlphabeticalOrder(
3625b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          clean_lines, linenum, canonical_include):
3626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'build/include_alpha', 4,
3627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Include "%s" not in alphabetical order' % include)
3628b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      include_state.SetLastHeader(canonical_include)
3629ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3630ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Look for any of the stream classes that are part of standard C++.
3631ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = _RE_PATTERN_INCLUDE.match(line)
3632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
3633ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include = match.group(2)
3634ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
3635ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Many unit tests use cout, so we exempt them.
3636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not _IsTestFilename(filename):
3637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'readability/streams', 3,
3638ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Streams are highly discouraged.')
3639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef _GetTextInside(text, start_pattern):
3642b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r"""Retrieves all the text between matching open and close parentheses.
3643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Given a string of lines and a regular expression string, retrieve all the text
3645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  following the expression and between opening punctuation symbols like
3646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  (, [, or {, and the matching close-punctuation symbol. This properly nested
3647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  occurrences of the punctuations, so for the text like
3648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    printf(a(), b(c()));
3649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
3650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  start_pattern must match string having an open punctuation symbol at the end.
3651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    text: The lines to extract text. Its comments and strings must be elided.
3654ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           It can be single line and can span multiple lines.
3655ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    start_pattern: The regexp string indicating where to start extracting
3656ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the text.
3657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
3658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The extracted text.
3659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    None if either the opening string or ending punctuation could not be found.
3660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3661ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably
3662ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # rewritten to use _GetTextInside (and use inferior regexp matching today).
3663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Give opening punctuations to get the matching close-punctuations.
3665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  matching_punctuation = {'(': ')', '{': '}', '[': ']'}
3666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  closing_punctuation = set(matching_punctuation.itervalues())
3667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Find the position to start extracting text.
3669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = re.search(start_pattern, text, re.M)
3670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not match:  # start_pattern not found in text.
3671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return None
3672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  start_position = match.end(0)
3673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  assert start_position > 0, (
3675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      'start_pattern must ends with an opening punctuation.')
3676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  assert text[start_position - 1] in matching_punctuation, (
3677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      'start_pattern must ends with an opening punctuation.')
3678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Stack of closing punctuations we expect to have in text after position.
3679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  punctuation_stack = [matching_punctuation[text[start_position - 1]]]
3680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  position = start_position
3681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  while punctuation_stack and position < len(text):
3682ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if text[position] == punctuation_stack[-1]:
3683ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      punctuation_stack.pop()
3684ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif text[position] in closing_punctuation:
3685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # A closing punctuation without matching opening punctuations.
3686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return None
3687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif text[position] in matching_punctuation:
3688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      punctuation_stack.append(matching_punctuation[text[position]])
3689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    position += 1
3690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if punctuation_stack:
3691ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Opening punctuations left without matching close-punctuations.
3692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return None
3693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # punctuations match.
3694ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return text[start_position:position - 1]
3695ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3696ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# Patterns for matching call-by-reference parameters.
3698b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#
3699b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# Supports nested templates up to 2 levels deep using this messy pattern:
3700b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#   < (?: < (?: < [^<>]*
3701b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#               >
3702b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#           |   [^<>] )*
3703b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#         >
3704b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#     |   [^<>] )*
3705b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#   >
3706b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*'  # =~ [[:alpha:]][[:alnum:]]*
3707b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_RE_PATTERN_TYPE = (
3708b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
3709b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'(?:\w|'
3710b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
3711b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'::)+')
3712b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# A call-by-reference parameter ends with '& identifier'.
3713b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_RE_PATTERN_REF_PARAM = re.compile(
3714b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
3715b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
3716b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# A call-by-const-reference parameter either ends with 'const& identifier'
3717b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian# or looks like 'const type& identifier' when 'type' is atomic.
3718b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian_RE_PATTERN_CONST_REF_PARAM = (
3719b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
3720b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
3721b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3722b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3723b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CheckLanguage(filename, clean_lines, linenum, file_extension,
3724b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                  include_state, nesting_state, error):
3725ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks rules from the 'C++ language rules' section of cppguide.html.
3726ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3727ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Some of these rules are hard to test (function overloading, using
3728ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  uint32 inappropriately), but we do the best we can.
3729ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3730ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
3731ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
3732ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
3733ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
3734ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    file_extension: The extension (without the dot) of the filename.
3735ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include_state: An _IncludeState instance in which the headers are inserted.
3736b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    nesting_state: A _NestingState instance which maintains information about
3737b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   the current stack of nested blocks being parsed.
3738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
3739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
3740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If the line is empty or consists of entirely a comment, no need to
3741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # check it.
3742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  line = clean_lines.elided[linenum]
3743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not line:
3744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
3745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = _RE_PATTERN_INCLUDE.search(line)
3747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
3748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
3749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
3750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3751b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Reset include state across preprocessor directives.  This is meant
3752b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # to silence warnings for conditional includes.
3753b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line):
3754b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    include_state.ResetSection()
3755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Make Windows paths like Unix.
3757ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  fullname = os.path.abspath(filename).replace('\\', '/')
3758ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3759ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(unknown): figure out if they're using default arguments in fn proto.
3760ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3761ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check to see if they're using an conversion function cast.
3762ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # I just try to capture the most common basic types, though there are more.
3763ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Parameterless conversion functions, such as bool(), are allowed as they are
3764ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # probably a member operator declaration or default constructor.
3765ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(
3766ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      r'(\bnew\s+)?\b'  # Grab 'new' operator, if it's there
3767b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
3768b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r'(\([^)].*)', line)
3769ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
3770b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    matched_new = match.group(1)
3771b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    matched_type = match.group(2)
3772b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    matched_funcptr = match.group(3)
3773b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3774ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # gMock methods are defined using some variant of MOCK_METHODx(name, type)
3775ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # where type may be float(), int(string), etc.  Without context they are
3776ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # virtually indistinguishable from int(x) casts. Likewise, gMock's
3777ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # MockCallback takes a template parameter of the form return_type(arg_type),
3778ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # which looks much like the cast we're trying to detect.
3779b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3780b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # std::function<> wrapper has a similar problem.
3781b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #
3782b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Return types for function pointers also look like casts if they
3783b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # don't have an extra space.
3784b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (matched_new is None and  # If new operator, then this isn't a cast
3785ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
3786b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             Search(r'\bMockCallback<.*>', line) or
3787b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             Search(r'\bstd::function<.*>', line)) and
3788b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        not (matched_funcptr and
3789b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian             Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
3790b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   matched_funcptr))):
3791ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Try a bit harder to catch gmock lines: the only place where
3792ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # something looks like an old-style cast is where we declare the
3793ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # return type of the mocked method, and the only time when we
3794ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # are missing context is if MOCK_METHOD was split across
3795b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # multiple lines.  The missing MOCK_METHOD is usually one or two
3796b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # lines back, so scan back one or two lines.
3797b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      #
3798b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # It's not possible for gmock macros to appear in the first 2
3799b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # lines, since the class head + section name takes up 2 lines.
3800b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (linenum < 2 or
3801b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
3802b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                     clean_lines.elided[linenum - 1]) or
3803b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian               Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
3804b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                     clean_lines.elided[linenum - 2]))):
3805ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        error(filename, linenum, 'readability/casting', 4,
3806ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Using deprecated casting style.  '
3807ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang              'Use static_cast<%s>(...) instead' %
3808b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              matched_type)
3809ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3810ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3811ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  'static_cast',
3812ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
3813ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3814ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # This doesn't catch all cases. Consider (const char * const)"hello".
3815ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #
3816ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # (char *) "foo" should always be a const_cast (reinterpret_cast won't
3817ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # compile).
3818ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3819ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     'const_cast', r'\((char\s?\*+\s?)\)\s*"', error):
3820ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pass
3821ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
3822ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Check pointer casts for other than string constants
3823ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
3824ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
3825ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3826ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # In addition, we look for people taking the address of a cast.  This
3827ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
3828ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # point where you think.
3829b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  match = Search(
3830b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r'(?:&\(([^)]+)\)[\w(])|'
3831b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line)
3832b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if match and match.group(1) != '*':
3833ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/casting', 4,
3834ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ('Are you taking an address of a cast?  '
3835ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           'This is dangerous: could be a temp var.  '
3836ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           'Take the address before doing the cast, rather than after'))
3837ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3838b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Create an extended_line, which is the concatenation of the current and
3839b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # next lines, for more effective checking of code that may span more than one
3840b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # line.
3841b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if linenum + 1 < clean_lines.NumLines():
3842b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    extended_line = line + clean_lines.elided[linenum + 1]
3843b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  else:
3844b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    extended_line = line
3845b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
3846ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check for people declaring static/global STL strings at the top level.
3847ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # This is dangerous because the C++ language does not guarantee that
3848ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # globals with constructors are initialized before the first access.
3849ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Match(
3850ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
3851ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line)
3852ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Make sure it's not a function.
3853ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Function template specialization looks like: "string foo<Type>(...".
3854ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Class template definitions look like: "string Foo<Type>::Method(...".
3855b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
3856b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Also ignore things that look like operators.  These are matched separately
3857b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # because operator names cross non-word boundaries.  If we change the pattern
3858b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # above, we would decrease the accuracy of matching identifiers.
3859b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (match and
3860b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not Search(r'\boperator\W', line) and
3861b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))):
3862ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/string', 4,
3863ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'For a static/global string constant, use a C style string instead: '
3864ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          '"%schar %s[]".' %
3865ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          (match.group(1), match.group(2)))
3866ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3867ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
3868ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/init', 4,
3869ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'You seem to be initializing a member variable with itself.')
3870ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3871ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if file_extension == 'h':
3872ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # TODO(unknown): check that 1-arg constructors are explicit.
3873ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                How to tell it's a constructor?
3874ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                (handled in CheckForNonStandardConstructs for now)
3875ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
3876ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    #                (level 1 error)
3877ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pass
3878ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3879ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check if people are using the verboten C basic types.  The only exception
3880ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # we regularly allow is "unsigned short port" for port.
3881ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\bshort port\b', line):
3882ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not Search(r'\bunsigned short port\b', line):
3883ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'runtime/int', 4,
3884ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Use "unsigned short" for ports, not "short"')
3885ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
3886ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Search(r'\b(short|long(?! +double)|long long)\b', line)
3887ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match:
3888ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'runtime/int', 4,
3889ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Use int16/int64/etc, rather than the C type %s' % match.group(1))
3890ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3891ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # When snprintf is used, the second argument shouldn't be a literal.
3892ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
3893ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match and match.group(2) != '0':
3894ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If 2nd arg is zero, snprintf is used to calculate size.
3895ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/printf', 3,
3896ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
3897ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'to snprintf.' % (match.group(1), match.group(2)))
3898ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3899ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check if some verboten C functions are being used.
3900ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\bsprintf\b', line):
3901ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/printf', 5,
3902ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Never use sprintf.  Use snprintf instead.')
3903ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'\b(strcpy|strcat)\b', line)
3904ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
3905ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/printf', 4,
3906ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Almost always, snprintf is better than %s' % match.group(1))
3907ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3908ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check if some verboten operator overloading is going on
3909ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(unknown): catch out-of-line unary operator&:
3910ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   class X {};
3911ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   int operator&(const X& x) { return 42; }  // unary operator&
3912ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The trick is it's hard to tell apart from binary operator&:
3913ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
3914ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\boperator\s*&\s*\(\s*\)', line):
3915ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/operator', 4,
3916ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Unary operator& is dangerous.  Do not use it.')
3917ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3918ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check for suspicious usage of "if" like
3919ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # } if (a == b) {
3920ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\}\s*if\s*\(', line):
3921ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'readability/braces', 4,
3922ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Did you mean "else if"? If not, start a new line for "if".')
3923ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3924ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check for potential format string bugs like printf(foo).
3925ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We constrain the pattern not to pick things like DocidForPrintf(foo).
3926ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
3927ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(sugawarayu): Catch the following case. Need to change the calling
3928ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # convention of the whole function to process multiple line to handle it.
3929ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #   printf(
3930ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
3931ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
3932ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if printf_args:
3933ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = Match(r'([\w.\->()]+)$', printf_args)
3934ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match and match.group(1) != '__VA_ARGS__':
3935ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      function_name = re.search(r'\b((?:string)?printf)\s*\(',
3936ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                line, re.I).group(1)
3937ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'runtime/printf', 4,
3938ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Potential format string bug. Do %s("%%s", %s) instead.'
3939ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            % (function_name, match.group(1)))
3940ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3941ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
3942ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
3943ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
3944ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/memset', 4,
3945ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Did you mean "memset(%s, 0, %s)"?'
3946ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          % (match.group(1), match.group(2)))
3947ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3948ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if Search(r'\busing namespace\b', line):
3949ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/namespaces', 5,
3950ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Do not use namespace using-directives.  '
3951ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Use using-declarations instead.')
3952ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3953ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Detect variable-length arrays.
3954ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
3955ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
3956ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      match.group(3).find(']') == -1):
3957ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Split the size using space and arithmetic operators as delimiters.
3958ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If any of the resulting tokens are not compile time constants then
3959ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # report the error.
3960ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
3961ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    is_const = True
3962ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    skip_next = False
3963ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for tok in tokens:
3964ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if skip_next:
3965ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        skip_next = False
3966ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        continue
3967ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3968ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Search(r'sizeof\(.+\)', tok): continue
3969ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Search(r'arraysize\(\w+\)', tok): continue
3970ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3971ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tok = tok.lstrip('(')
3972ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      tok = tok.rstrip(')')
3973ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not tok: continue
3974ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r'\d+', tok): continue
3975ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r'0[xX][0-9a-fA-F]+', tok): continue
3976ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r'k[A-Z0-9]\w*', tok): continue
3977ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
3978ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
3979ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # A catch all for tricky sizeof cases, including 'sizeof expression',
3980ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
3981ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # requires skipping the next token because we split on ' ' and '*'.
3982ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if tok.startswith('sizeof'):
3983ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        skip_next = True
3984ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        continue
3985ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      is_const = False
3986ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      break
3987ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not is_const:
3988ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'runtime/arrays', 1,
3989ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Do not use variable-length arrays.  Use an appropriately named '
3990ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            "('k' followed by CamelCase) compile-time constant for the size.")
3991ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
3992ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
3993ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
3994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # in the class declaration.
3995ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Match(
3996ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      (r'\s*'
3997ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
3998ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       r'\(.*\);$'),
3999ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line)
4000ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match and linenum + 1 < clean_lines.NumLines():
4001ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    next_line = clean_lines.elided[linenum + 1]
4002ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # We allow some, but not all, declarations of variables to be present
4003ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # in the statement that defines the class.  The [\w\*,\s]* fragment of
4004ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # the regular expression below allows users to declare instances of
4005ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # the class or pointers to instances, but not less common types such
4006ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # as function pointers or arrays.  It's a tradeoff between allowing
4007ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # reasonable code and avoiding trying to parse more C++ using regexps.
4008ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not Search(r'^\s*}[\w\*,\s]*;', next_line):
4009ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, linenum, 'readability/constructors', 3,
4010ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            match.group(1) + ' should be the last thing in the class')
4011ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4012ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Check for use of unnamed namespaces in header files.  Registration
4013ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # macros are typically OK, so we allow use of "namespace {" on lines
4014ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # that end with backslashes.
4015ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (file_extension == 'h'
4016ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      and Search(r'\bnamespace\s*{', line)
4017ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      and line[-1] != '\\'):
4018ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/namespaces', 4,
4019ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Do not use unnamed namespaces in header files.  See '
4020ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
4021ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ' for more information.')
4022ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4023b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniandef CheckForNonConstReference(filename, clean_lines, linenum,
4024b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                              nesting_state, error):
4025b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """Check for non-const references.
4026b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4027b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Separate from CheckLanguage since it scans backwards from current
4028b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  line, instead of scanning forward.
4029b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4030b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  Args:
4031b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    filename: The name of the current file.
4032b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    clean_lines: A CleansedLines instance containing the file.
4033b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    linenum: The number of the line to check.
4034b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    nesting_state: A _NestingState instance which maintains information about
4035b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   the current stack of nested blocks being parsed.
4036b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    error: The function to call with any errors found.
4037b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  """
4038b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Do nothing if there is no '&' on current line.
4039b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  line = clean_lines.elided[linenum]
4040b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if '&' not in line:
4041b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return
4042b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4043b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Long type names may be broken across multiple lines, usually in one
4044b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # of these forms:
4045b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   LongType
4046b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #       ::LongTypeContinued &identifier
4047b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   LongType::
4048b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #       LongTypeContinued &identifier
4049b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   LongType<
4050b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #       ...>::LongTypeContinued &identifier
4051b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
4052b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # If we detected a type split across two lines, join the previous
4053b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # line to current line so that we can match const references
4054b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # accordingly.
4055b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
4056b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Note that this only scans back one line, since scanning back
4057b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # arbitrary number of lines would be expensive.  If you have a type
4058b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # that spans more than 2 lines, please use a typedef.
4059b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if linenum > 1:
4060b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    previous = None
4061b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
4062b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # previous_line\n + ::current_line
4063b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
4064b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                        clean_lines.elided[linenum - 1])
4065b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
4066b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # previous_line::\n + current_line
4067b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
4068b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                        clean_lines.elided[linenum - 1])
4069b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if previous:
4070b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      line = previous.group(1) + line.lstrip()
4071b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    else:
4072b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      # Check for templated parameter that is split across multiple lines
4073b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      endpos = line.rfind('>')
4074b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if endpos > -1:
4075b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        (_, startline, startpos) = ReverseCloseExpression(
4076b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            clean_lines, linenum, endpos)
4077b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if startpos > -1 and startline < linenum:
4078b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          # Found the matching < on an earlier line, collect all
4079b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          # pieces up to current line.
4080b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          line = ''
4081b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          for i in xrange(startline, linenum + 1):
4082b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            line += clean_lines.elided[i].strip()
4083b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4084b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # Check for non-const references in function parameters.  A single '&' may
4085b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # found in the following places:
4086b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   inside expression: binary & for bitwise AND
4087b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   inside expression: unary & for taking the address of something
4088b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   inside declarators: reference parameter
4089b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # We will exclude the first two cases by checking that we are not inside a
4090b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # function body, including one that was just introduced by a trailing '{'.
4091b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # TODO(unknwon): Doesn't account for preprocessor directives.
4092b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
4093b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  check_params = False
4094b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if not nesting_state.stack:
4095b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    check_params = True  # top level
4096b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  elif (isinstance(nesting_state.stack[-1], _ClassInfo) or
4097b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        isinstance(nesting_state.stack[-1], _NamespaceInfo)):
4098b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    check_params = True  # within class or namespace
4099b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  elif Match(r'.*{\s*$', line):
4100b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (len(nesting_state.stack) == 1 or
4101b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        isinstance(nesting_state.stack[-2], _ClassInfo) or
4102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        isinstance(nesting_state.stack[-2], _NamespaceInfo)):
4103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      check_params = True  # just opened global/class/namespace block
4104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # We allow non-const references in a few standard places, like functions
4105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # called "swap()" or iostream operators like "<<" or ">>".  Do not check
4106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # those function parameters.
4107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
4108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # We also accept & in static_assert, which looks like a function but
4109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # it's actually a declaration expression.
4110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
4111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                           r'operator\s*[<>][<>]|'
4112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                           r'static_assert|COMPILE_ASSERT'
4113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                           r')\s*\(')
4114b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Search(whitelisted_functions, line):
4115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    check_params = False
4116b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  elif not Search(r'\S+\([^)]*$', line):
4117b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Don't see a whitelisted function on this line.  Actually we
4118b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # didn't see any function name on this line, so this is likely a
4119b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # multi-line parameter list.  Try a bit harder to catch this case.
4120b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    for i in xrange(2):
4121b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (linenum > i and
4122b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
4123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        check_params = False
4124b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        break
4125b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if check_params:
4127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
4128b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
4129b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
4130b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        error(filename, linenum, 'runtime/references', 2,
4131b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'Is this a non-const reference? '
4132b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              'If so, make const or use a pointer: ' +
4133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              ReplaceAll(' *<', '<', parameter))
4134b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
4137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    error):
4138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Checks for a C-style cast by looking for the pattern.
4139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
4142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
4143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: The line of code to check.
4144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    raw_line: The raw line of code to check, with comments.
4145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    cast_type: The string for the C++ cast to recommend.  This is either
4146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      reinterpret_cast, static_cast, or const_cast, depending.
4147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    pattern: The regular expression used to find C-style casts.
4148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
4149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
4151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True if an error was emitted.
4152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    False otherwise.
4153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = Search(pattern, line)
4155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not match:
4156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
4157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # e.g., sizeof(int)
4159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
4160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if sizeof_match:
4161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'runtime/sizeof', 1,
4162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'Using sizeof(type).  Use sizeof(varname) instead if possible')
4163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return True
4164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # operator++(int) and operator--(int)
4166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (line[0:match.start(1) - 1].endswith(' operator++') or
4167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      line[0:match.start(1) - 1].endswith(' operator--')):
4168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
4169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4170b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # A single unnamed argument for a function tends to look like old
4171b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # style cast.  If we see those, don't issue warnings for deprecated
4172b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # casts, instead issue warnings for unnamed arguments where
4173b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # appropriate.
4174b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
4175b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # These are things that we want warnings for, since the style guide
4176b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # explicitly require all parameters to be named:
4177b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   Function(int);
4178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   Function(int) {
4179b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   ConstMember(int) const;
4180b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   ConstMember(int) const {
4181b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   ExceptionMember(int) throw (...);
4182b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   ExceptionMember(int) throw (...) {
4183b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   PureVirtual(int) = 0;
4184b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #
4185b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # These are functions of some sort, where the compiler would be fine
4186b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # if they had named parameters, but people often omit those
4187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  # identifiers to reduce clutter:
4188b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   (FunctionPointer)(int);
4189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   (FunctionPointer)(int) = value;
4190b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   Function((function_pointer_arg)(int))
4191b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   <TemplateArgument(int)>;
4192b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  #   <(FunctionPointerTemplateArgument)(int)>;
4193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  remainder = line[match.end(0):]
4194b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if Match(r'^\s*(?:;|const\b|throw\b|=|>|\{|\))', remainder):
4195b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Looks like an unnamed parameter.
4196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4197b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Don't warn on any kind of template arguments.
4198b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if Match(r'^\s*>', remainder):
4199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return False
4200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4201b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Don't warn on assignments to function pointers, but keep warnings for
4202b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # unnamed parameters to pure virtual functions.  Note that this pattern
4203b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # will also pass on assignments of "0" to function pointers, but the
4204b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # preferred values for those would be "nullptr" or "NULL".
4205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder)
4206b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if matched_zero and matched_zero.group(1) != '0':
4207b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return False
4208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Don't warn on function pointer declarations.  For this we need
4210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # to check what came before the "(type)" string.
4211b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if Match(r'.*\)\s*$', line[0:match.start(0)]):
4212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return False
4213b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Don't warn if the parameter is named with block comments, e.g.:
4215b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    #  Function(int /*unused_param*/);
4216b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if '/*' in raw_line:
4217b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return False
4218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
4219b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    # Passed all filters, issue warning here.
4220b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    error(filename, linenum, 'readability/function', 3,
4221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          'All parameters should be named in a function')
4222ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return True
4223ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4224ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # At this point, all that should be left is actual casts.
4225ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  error(filename, linenum, 'readability/casting', 4,
4226ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        'Using C-style cast.  Use %s<%s>(...) instead' %
4227ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        (cast_type, match.group(1)))
4228ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4229ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return True
4230ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4231ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_HEADERS_CONTAINING_TEMPLATES = (
4233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<deque>', ('deque',)),
4234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<functional>', ('unary_function', 'binary_function',
4235ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'plus', 'minus', 'multiplies', 'divides', 'modulus',
4236ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'negate',
4237ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'equal_to', 'not_equal_to', 'greater', 'less',
4238ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'greater_equal', 'less_equal',
4239ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'logical_and', 'logical_or', 'logical_not',
4240ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'unary_negate', 'not1', 'binary_negate', 'not2',
4241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'bind1st', 'bind2nd',
4242ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'pointer_to_unary_function',
4243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'pointer_to_binary_function',
4244ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'ptr_fun',
4245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
4246ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'mem_fun_ref_t',
4247ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'const_mem_fun_t', 'const_mem_fun1_t',
4248ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
4249ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                      'mem_fun_ref',
4250ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                     )),
4251ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<limits>', ('numeric_limits',)),
4252ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<list>', ('list',)),
4253ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<map>', ('map', 'multimap',)),
4254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<memory>', ('allocator',)),
4255ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<queue>', ('queue', 'priority_queue',)),
4256ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<set>', ('set', 'multiset',)),
4257ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<stack>', ('stack',)),
4258ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<string>', ('char_traits', 'basic_string',)),
4259ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<utility>', ('pair',)),
4260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<vector>', ('vector',)),
4261ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4262ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # gcc extensions.
4263ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Note: std::hash is their hash, ::hash is our hash
4264ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<hash_map>', ('hash_map', 'hash_multimap',)),
4265ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<hash_set>', ('hash_set', 'hash_multiset',)),
4266ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ('<slist>', ('slist',)),
4267ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    )
4268ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4269ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_STRING = re.compile(r'\bstring\b')
4270ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4271ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_re_pattern_algorithm_header = []
4272ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangfor _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
4273ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                  'transform'):
4274ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
4275ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # type::max().
4276ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _re_pattern_algorithm_header.append(
4277ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
4278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       _template,
4279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang       '<algorithm>'))
4280ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4281ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_re_pattern_templates = []
4282ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangfor _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
4283ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for _template in _templates:
4284ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    _re_pattern_templates.append(
4285ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
4286ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _template + '<>',
4287ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang         _header))
4288ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4289ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4290ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef FilesBelongToSameModule(filename_cc, filename_h):
4291ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Check if these two filenames belong to the same module.
4292ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4293ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  The concept of a 'module' here is a as follows:
4294ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
4295ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  same 'module' if they are in the same directory.
4296ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  some/path/public/xyzzy and some/path/internal/xyzzy are also considered
4297ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  to belong to the same module here.
4298ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4299ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  If the filename_cc contains a longer path than the filename_h, for example,
4300ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  '/absolute/path/to/base/sysinfo.cc', and this file would include
4301ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  'base/sysinfo.h', this function also produces the prefix needed to open the
4302ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  header. This is used by the caller of this function to more robustly open the
4303ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  header file. We don't have access to the real include paths in this context,
4304ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  so we need this guesswork here.
4305ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4306ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
4307ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  according to this implementation. Because of this, this function gives
4308ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  some false positives. This should be sufficiently rare in practice.
4309ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4310ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4311ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename_cc: is the path for the .cc file
4312ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename_h: is the path for the header path
4313ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4314ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
4315ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Tuple with a bool and a string:
4316ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    bool: True if filename_cc and filename_h belong to the same module.
4317ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    string: the additional prefix needed to open the header file.
4318ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4319ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4320ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not filename_cc.endswith('.cc'):
4321ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (False, '')
4322ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_cc = filename_cc[:-len('.cc')]
4323ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if filename_cc.endswith('_unittest'):
4324ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename_cc = filename_cc[:-len('_unittest')]
4325ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  elif filename_cc.endswith('_test'):
4326ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename_cc = filename_cc[:-len('_test')]
4327ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_cc = filename_cc.replace('/public/', '/')
4328ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_cc = filename_cc.replace('/internal/', '/')
4329ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4330ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not filename_h.endswith('.h'):
4331ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return (False, '')
4332ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_h = filename_h[:-len('.h')]
4333ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if filename_h.endswith('-inl'):
4334ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename_h = filename_h[:-len('-inl')]
4335ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_h = filename_h.replace('/public/', '/')
4336ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filename_h = filename_h.replace('/internal/', '/')
4337ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4338ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  files_belong_to_same_module = filename_cc.endswith(filename_h)
4339ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  common_path = ''
4340ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if files_belong_to_same_module:
4341ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    common_path = filename_cc[:-len(filename_h)]
4342ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return files_belong_to_same_module, common_path
4343ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4344ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4345ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef UpdateIncludeState(filename, include_state, io=codecs):
4346ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Fill up the include_state with new includes found from the file.
4347ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4348ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4349ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: the name of the header to read.
4350ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include_state: an _IncludeState instance in which the headers are inserted.
4351ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    io: The io factory to use to read the file. Provided for testability.
4352ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4353ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
4354ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    True if a header was succesfully added. False otherwise.
4355ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4356ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  headerfile = None
4357ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  try:
4358ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    headerfile = io.open(filename, 'r', 'utf8', 'replace')
4359ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  except IOError:
4360ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return False
4361ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  linenum = 0
4362ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for line in headerfile:
4363ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum += 1
4364ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_line = CleanseComments(line)
4365ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    match = _RE_PATTERN_INCLUDE.search(clean_line)
4366ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if match:
4367ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include = match.group(2)
4368ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # The value formatting is cute, but not really used right now.
4369ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # What matters here is that the key is in include_state.
4370ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      include_state.setdefault(include, '%s:%d' % (filename, linenum))
4371ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return True
4372ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4373ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4374ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
4375ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                              io=codecs):
4376ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Reports for missing stl includes.
4377ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4378ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  This function will output warnings to make sure you are including the headers
4379ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  necessary for the stl containers and functions that you use. We only give one
4380ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  reason to include a header. For example, if you use both equal_to<> and
4381ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  less<> in a .h file, only one (the latter in the file) of these will be
4382ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  reported as a reason to include the <functional>.
4383ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4384ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4385ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
4386ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
4387ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include_state: An _IncludeState instance.
4388ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
4389ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    io: The IO factory to use to read the header file. Provided for unittest
4390ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        injection.
4391ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4392ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  required = {}  # A map of header name to linenumber and the template entity.
4393ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 # Example of required: { '<functional>': (1219, 'less<>') }
4394ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4395ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for linenum in xrange(clean_lines.NumLines()):
4396ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line = clean_lines.elided[linenum]
4397ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not line or line[0] == '#':
4398ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      continue
4399ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4400ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # String is special -- it is a non-templatized type in STL.
4401ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    matched = _RE_PATTERN_STRING.search(line)
4402ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if matched:
4403ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Don't warn about strings in non-STL namespaces:
4404ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # (We check only the first match per line; good enough.)
4405ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      prefix = line[:matched.start()]
4406ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if prefix.endswith('std::') or not prefix.endswith('::'):
4407ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        required['<string>'] = (linenum, 'string')
4408ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4409ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for pattern, template, header in _re_pattern_algorithm_header:
4410ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if pattern.search(line):
4411ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        required[header] = (linenum, template)
4412ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4413ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # The following function is just a speed up, no semantics are changed.
4414ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if not '<' in line:  # Reduces the cpu time usage by skipping lines.
4415ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      continue
4416ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4417ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for pattern, template, header in _re_pattern_templates:
4418ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if pattern.search(line):
4419ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        required[header] = (linenum, template)
4420ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4421ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # The policy is that if you #include something in foo.h you don't need to
4422ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # include it again in foo.cc. Here, we will look at possible includes.
4423ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Let's copy the include_state so it is only messed up within this function.
4424ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  include_state = include_state.copy()
4425ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4426ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Did we find the header for this file (if any) and succesfully load it?
4427ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  header_found = False
4428ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4429ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Use the absolute path so that matching works properly.
4430ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  abs_filename = FileInfo(filename).FullName()
4431ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4432ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # For Emacs's flymake.
4433ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
4434ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # by flymake and that file name might end with '_flymake.cc'. In that case,
4435ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # restore original file name here so that the corresponding header file can be
4436ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # found.
4437ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
4438ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # instead of 'foo_flymake.h'
4439ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
4440ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4441ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # include_state is modified during iteration, so we iterate over a copy of
4442ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # the keys.
4443ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  header_keys = include_state.keys()
4444ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for header in header_keys:
4445ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
4446ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    fullpath = common_path + header
4447ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if same_module and UpdateIncludeState(fullpath, include_state, io):
4448ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      header_found = True
4449ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4450ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # If we can't find the header file for a .cc, assume it's because we don't
4451ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # know where to look. In that case we'll give up as we're not sure they
4452ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # didn't include it in the .h file.
4453ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # TODO(unknown): Do a better job of finding .h files so we are confident that
4454ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # not having the .h file means there isn't one.
4455ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if filename.endswith('.cc') and not header_found:
4456ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
4457ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4458ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # All the lines have been processed, report the errors found.
4459ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for required_header_unstripped in required:
4460ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    template = required[required_header_unstripped][1]
4461ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if required_header_unstripped.strip('<>"') not in include_state:
4462ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error(filename, required[required_header_unstripped][0],
4463ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'build/include_what_you_use', 4,
4464ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'Add #include ' + required_header_unstripped + ' for ' + template)
4465ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4466ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4467ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
4468ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4469ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4470ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
4471ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Check that make_pair's template arguments are deduced.
4472ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4473ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are
4474ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  specified explicitly, and such use isn't intended in any case.
4475ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4476ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4477ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the current file.
4478ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: A CleansedLines instance containing the file.
4479ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    linenum: The number of the line to check.
4480ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: The function to call with any errors found.
4481ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4482b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  line = clean_lines.elided[linenum]
4483ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
4484ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if match:
4485ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error(filename, linenum, 'build/explicit_make_pair',
4486ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          4,  # 4 = high confidence
4487ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          'For C++11-compatibility, omit template arguments from make_pair'
4488ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          ' OR use pair directly OR if appropriate, construct a pair directly')
4489ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4490ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4491ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ProcessLine(filename, file_extension, clean_lines, line,
4492ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                include_state, function_state, nesting_state, error,
4493ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                extra_check_functions=[]):
4494ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Processes a single line in the file.
4495ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4496ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4497ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: Filename of the file that is being processed.
4498ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    file_extension: The extension (dot not included) of the file.
4499ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    clean_lines: An array of strings, each representing a line of the file,
4500ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                 with comments stripped.
4501ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    line: Number of line being processed.
4502ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    include_state: An _IncludeState instance in which the headers are inserted.
4503ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    function_state: A _FunctionState instance which counts function lines, etc.
4504ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    nesting_state: A _NestingState instance which maintains information about
4505ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                   the current stack of nested blocks being parsed.
4506ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: A callable to which errors are reported, which takes 4 arguments:
4507ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           filename, line number, error level, and message
4508ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    extra_check_functions: An array of additional check functions that will be
4509ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           run on each source line. Each function takes 4
4510ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           arguments: filename, clean_lines, line, error
4511ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4512ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  raw_lines = clean_lines.raw_lines
4513ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ParseNolintSuppressions(filename, raw_lines[line], line, error)
4514ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nesting_state.Update(filename, clean_lines, line, error)
4515ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if nesting_state.stack and nesting_state.stack[-1].inline_asm != _NO_ASM:
4516ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
4517ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
4518ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
4519ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
4520ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckLanguage(filename, clean_lines, line, file_extension, include_state,
4521b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                nesting_state, error)
4522b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
4523ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForNonStandardConstructs(filename, clean_lines, line,
4524ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                nesting_state, error)
4525b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  CheckVlogArguments(filename, clean_lines, line, error)
4526ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckPosixThreading(filename, clean_lines, line, error)
4527ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckInvalidIncrement(filename, clean_lines, line, error)
4528ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckMakePairUsesDeduction(filename, clean_lines, line, error)
4529ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for check_fn in extra_check_functions:
4530ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    check_fn(filename, clean_lines, line, error)
4531ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4532ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ProcessFileData(filename, file_extension, lines, error,
4533ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    extra_check_functions=[]):
4534ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Performs lint checks and reports any errors to the given error function.
4535ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4536ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4537ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: Filename of the file that is being processed.
4538ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    file_extension: The extension (dot not included) of the file.
4539ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    lines: An array of strings, each representing a line of the file, with the
4540ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           last element being empty if the file is terminated with a newline.
4541ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error: A callable to which errors are reported, which takes 4 arguments:
4542ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           filename, line number, error level, and message
4543ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    extra_check_functions: An array of additional check functions that will be
4544ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           run on each source line. Each function takes 4
4545ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           arguments: filename, clean_lines, line, error
4546ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4547ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  lines = (['// marker so line numbers and indices both start at 1'] + lines +
4548ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang           ['// marker so line numbers end in a known way'])
4549ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4550ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  include_state = _IncludeState()
4551ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  function_state = _FunctionState()
4552ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  nesting_state = _NestingState()
4553ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4554ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ResetNolintSuppressions()
4555ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4556ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForCopyright(filename, lines, error)
4557ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4558ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if file_extension == 'h':
4559ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    CheckForHeaderGuard(filename, lines, error)
4560ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4561ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  RemoveMultiLineComments(filename, lines, error)
4562ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  clean_lines = CleansedLines(lines)
4563ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for line in xrange(clean_lines.NumLines()):
4564ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ProcessLine(filename, file_extension, clean_lines, line,
4565ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                include_state, function_state, nesting_state, error,
4566ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                extra_check_functions)
4567b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nesting_state.CheckCompletedBlocks(filename, error)
4568ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4569ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
4570ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4571ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # We check here rather than inside ProcessLine so that we see raw
4572ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # lines rather than "cleaned" lines.
4573b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  CheckForBadCharacters(filename, lines, error)
4574ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4575ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  CheckForNewlineAtEOF(filename, lines, error)
4576ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4577ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ProcessFile(filename, vlevel, extra_check_functions=[]):
4578ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Does google-lint on a single file.
4579ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4580ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4581ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    filename: The name of the file to parse.
4582ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4583ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    vlevel: The level of errors to report.  Every error of confidence
4584ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    >= verbose_level will be reported.  0 is a good default.
4585ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4586ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    extra_check_functions: An array of additional check functions that will be
4587ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           run on each source line. Each function takes 4
4588ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           arguments: filename, clean_lines, line, error
4589ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4590ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4591ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SetVerboseLevel(vlevel)
4592ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4593ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  try:
4594ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Support the UNIX convention of using "-" for stdin.  Note that
4595ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # we are not opening the file with universal newline support
4596ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # (which codecs doesn't support anyway), so the resulting lines do
4597ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # contain trailing '\r' characters if we are reading a file that
4598ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # has CRLF endings.
4599ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # If after the split a trailing '\r' is present, it is removed
4600ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # below. If it is not expected to be present (i.e. os.linesep !=
4601ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # '\r\n' as in Windows), a warning is issued below if this file
4602ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # is processed.
4603ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4604ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if filename == '-':
4605ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      lines = codecs.StreamReaderWriter(sys.stdin,
4606ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                        codecs.getreader('utf8'),
4607ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                        codecs.getwriter('utf8'),
4608ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                        'replace').read().split('\n')
4609ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    else:
4610ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
4611ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4612ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    carriage_return_found = False
4613ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    # Remove trailing '\r'.
4614ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    for linenum in range(len(lines)):
4615ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if lines[linenum].endswith('\r'):
4616ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        lines[linenum] = lines[linenum].rstrip('\r')
4617ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        carriage_return_found = True
4618ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4619ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  except IOError:
4620ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    sys.stderr.write(
4621ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        "Skipping input '%s': Can't open for reading\n" % filename)
4622ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return
4623ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4624ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Note, if no dot is found, this will give the entire filename as the ext.
4625ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  file_extension = filename[filename.rfind('.') + 1:]
4626ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4627ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # When reading from stdin, the extension is unknown, so no cpplint tests
4628ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # should rely on the extension.
4629b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if filename != '-' and file_extension not in _valid_extensions:
4630b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    sys.stderr.write('Ignoring %s; not a valid file name '
4631b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                     '(%s)\n' % (filename, ', '.join(_valid_extensions)))
4632ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
4633ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ProcessFileData(filename, file_extension, lines, Error,
4634ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    extra_check_functions)
4635ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if carriage_return_found and os.linesep != '\r\n':
4636ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # Use 0 for linenum since outputting only one error for potentially
4637ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      # several lines.
4638ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      Error(filename, 0, 'whitespace/newline', 1,
4639ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'One or more unexpected \\r (^M) found;'
4640ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            'better to use only a \\n')
4641ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4642ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.stderr.write('Done processing %s\n' % filename)
4643ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4644ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4645ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef PrintUsage(message):
4646ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Prints a brief usage string and exits, optionally with an error message.
4647ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4648ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4649ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    message: The optional error message.
4650ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4651ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.stderr.write(_USAGE)
4652ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if message:
4653ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    sys.exit('\nFATAL ERROR: ' + message)
4654ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  else:
4655ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    sys.exit(1)
4656ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4657ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4658ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef PrintCategories():
4659ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Prints a list of all the error-categories used by error messages.
4660ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4661ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  These are the categories used to filter messages via --filter.
4662ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4663ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.stderr.write(''.join('  %s\n' % cat for cat in _ERROR_CATEGORIES))
4664ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.exit(0)
4665ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4666ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4667ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef ParseArguments(args):
4668ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """Parses the command line arguments.
4669ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4670ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  This may set the output format and verbosity level as side-effects.
4671ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4672ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Args:
4673ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    args: The command line arguments:
4674ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4675ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Returns:
4676ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    The list of filenames to lint.
4677ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  """
4678ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  try:
4679ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
4680ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                                 'counting=',
4681ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                                 'filter=',
4682b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                                 'root=',
4683b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                                 'linelength=',
4684b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                                 'extensions='])
4685ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  except getopt.GetoptError:
4686ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    PrintUsage('Invalid arguments.')
4687ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4688ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  verbosity = _VerboseLevel()
4689ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  output_format = _OutputFormat()
4690ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filters = ''
4691ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  counting_style = ''
4692ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4693ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for (opt, val) in opts:
4694ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if opt == '--help':
4695ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      PrintUsage(None)
4696ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif opt == '--output':
4697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if val not in ('emacs', 'vs7', 'eclipse'):
4698b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
4699ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      output_format = val
4700ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif opt == '--verbose':
4701ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      verbosity = int(val)
4702ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif opt == '--filter':
4703ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      filters = val
4704ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if not filters:
4705ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        PrintCategories()
4706ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif opt == '--counting':
4707ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      if val not in ('total', 'toplevel', 'detailed'):
4708ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        PrintUsage('Valid counting options are total, toplevel, and detailed')
4709ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      counting_style = val
4710ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    elif opt == '--root':
4711ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      global _root
4712ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      _root = val
4713b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif opt == '--linelength':
4714b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      global _line_length
4715b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      try:
4716b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          _line_length = int(val)
4717b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      except ValueError:
4718b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          PrintUsage('Line length must be digits.')
4719b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    elif opt == '--extensions':
4720b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      global _valid_extensions
4721b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      try:
4722b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          _valid_extensions = set(val.split(','))
4723b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      except ValueError:
4724b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          PrintUsage('Extensions must be comma seperated list.')
4725ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4726ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if not filenames:
4727ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    PrintUsage('No files were specified.')
4728ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4729ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SetOutputFormat(output_format)
4730ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SetVerboseLevel(verbosity)
4731ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SetFilters(filters)
4732ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _SetCountingStyle(counting_style)
4733ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4734ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return filenames
4735ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4736ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4737ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangdef main():
4738ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  filenames = ParseArguments(sys.argv[1:])
4739ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4740ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # Change stderr to write with replacement characters so we don't die
4741ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  # if we try to print something containing non-ASCII characters.
4742ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.stderr = codecs.StreamReaderWriter(sys.stderr,
4743ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                         codecs.getreader('utf8'),
4744ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                         codecs.getwriter('utf8'),
4745ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                         'replace')
4746ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4747ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _cpplint_state.ResetErrorCounts()
4748ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  for filename in filenames:
4749ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ProcessFile(filename, _cpplint_state.verbose_level)
4750ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  _cpplint_state.PrintErrorCounts()
4751ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4752ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  sys.exit(_cpplint_state.error_count > 0)
4753ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4754ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
4755ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangif __name__ == '__main__':
4756ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  main()
4757