blob: 4b067d473b32970301ea1ad158aed24e452bea06 [file] [log] [blame]
erg@chromium.orgd528f8b2012-05-11 17:31:08 +00001#!/usr/bin/env python
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002#
erg@google.com26970fa2009-11-17 18:07:32 +00003# Copyright (c) 2009 Google Inc. All rights reserved.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004#
erg@google.com26970fa2009-11-17 18:07:32 +00005# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00008#
erg@google.com26970fa2009-11-17 18:07:32 +00009# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000018#
erg@google.com26970fa2009-11-17 18:07:32 +000019# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000030
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000031"""Does google-lint on c++ files.
32
33The goal of this script is to identify places in the code that *may*
34be in non-compliance with google style. It does not attempt to fix
35up these problems -- the point is to educate. It does also not
36attempt to find all problems, or to ensure that everything it does
37find is legitimately a problem.
38
39In particular, we can get very confused by /* and // inside strings!
40We do a small hack, which is to ignore //'s with "'s after them on the
41same line, but it is far from perfect (in either direction).
42"""
43
44import codecs
mazda@chromium.org3fffcec2013-06-07 01:04:53 +000045import copy
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000046import getopt
47import math # for log
48import os
49import re
50import sre_compile
51import string
52import sys
53import unicodedata
54
55
56_USAGE = """
57Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +000058 [--counting=total|toplevel|detailed] [--root=subdir]
59 [--linelength=digits]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000060 <file> [file] ...
61
62 The style guidelines this tries to follow are those in
63 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
64
65 Every problem is given a confidence score from 1-5, with 5 meaning we are
66 certain of the problem, and 1 meaning it could be a legitimate construct.
67 This will miss some errors, and is not a substitute for a code review.
68
erg@google.com35589e62010-11-17 18:58:16 +000069 To suppress false-positive errors of a certain category, add a
70 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
71 suppresses errors of all categories on that line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000072
73 The files passed in will be linted; at least one file must be provided.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +000074 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the
75 extensions with the --extensions flag.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000076
77 Flags:
78
79 output=vs7
80 By default, the output is formatted to ease emacs parsing. Visual Studio
81 compatible output (vs7) may also be used. Other formats are unsupported.
82
83 verbose=#
84 Specify a number 0-5 to restrict errors to certain verbosity levels.
85
86 filter=-x,+y,...
87 Specify a comma-separated list of category-filters to apply: only
88 error messages whose category names pass the filters will be printed.
89 (Category names are printed with the message and look like
90 "[whitespace/indent]".) Filters are evaluated left to right.
91 "-FOO" and "FOO" means "do not print categories that start with FOO".
92 "+FOO" means "do print categories that start with FOO".
93
94 Examples: --filter=-whitespace,+whitespace/braces
95 --filter=whitespace,runtime/printf,+runtime/printf_format
96 --filter=-,+build/include_what_you_use
97
98 To see a list of all the categories used in cpplint, pass no arg:
99 --filter=
erg@google.com26970fa2009-11-17 18:07:32 +0000100
101 counting=total|toplevel|detailed
102 The total number of errors found is always printed. If
103 'toplevel' is provided, then the count of errors in each of
104 the top-level categories like 'build' and 'whitespace' will
105 also be printed. If 'detailed' is provided, then a count
106 is provided for each category like 'build/class'.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000107
108 root=subdir
109 The root directory used for deriving header guard CPP variable.
110 By default, the header guard CPP variable is calculated as the relative
111 path to the directory that contains .git, .hg, or .svn. When this flag
112 is specified, the relative path is calculated from the specified
113 directory. If the specified directory does not exist, this flag is
114 ignored.
115
116 Examples:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000117 Assuming that src/.git exists, the header guard CPP variables for
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000118 src/chrome/browser/ui/browser.h are:
119
120 No flag => CHROME_BROWSER_UI_BROWSER_H_
121 --root=chrome => BROWSER_UI_BROWSER_H_
122 --root=chrome/browser => UI_BROWSER_H_
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000123
124 linelength=digits
125 This is the allowed line length for the project. The default value is
126 80 characters.
127
128 Examples:
129 --linelength=120
130
131 extensions=extension,extension,...
132 The allowed file extensions that cpplint will check
133
134 Examples:
135 --extensions=hpp,cpp
avakulenko@google.com17449932014-07-28 22:13:33 +0000136
137 cpplint.py supports per-directory configurations specified in CPPLINT.cfg
138 files. CPPLINT.cfg file can contain a number of key=value pairs.
139 Currently the following options are supported:
140
141 set noparent
142 filter=+filter1,-filter2,...
143 exclude_files=regex
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000144 linelength=80
avakulenko@google.com17449932014-07-28 22:13:33 +0000145
146 "set noparent" option prevents cpplint from traversing directory tree
147 upwards looking for more .cfg files in parent directories. This option
148 is usually placed in the top-level project directory.
149
150 The "filter" option is similar in function to --filter flag. It specifies
151 message filters in addition to the |_DEFAULT_FILTERS| and those specified
152 through --filter command-line flag.
153
154 "exclude_files" allows to specify a regular expression to be matched against
155 a file name. If the expression matches, the file is skipped and not run
156 through liner.
157
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000158 "linelength" allows to specify the allowed line length for the project.
159
avakulenko@google.com17449932014-07-28 22:13:33 +0000160 CPPLINT.cfg has an effect on files in the same directory and all
161 sub-directories, unless overridden by a nested configuration file.
162
163 Example file:
164 filter=-build/include_order,+build/include_alpha
165 exclude_files=.*\.cc
166
167 The above example disables build/include_order warning and enables
168 build/include_alpha as well as excludes all .cc from being
169 processed by linter, in the current directory (where the .cfg
170 file is located) and all sub-directories.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000171"""
172
173# We categorize each error message we print. Here are the categories.
174# We want an explicit list so we can list them all in cpplint --filter=.
175# If you add a new error message with a new category, add it to the list
176# here! cpplint_unittest.py should tell you if you forget to do this.
erg@google.com35589e62010-11-17 18:58:16 +0000177_ERROR_CATEGORIES = [
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000178 'build/class',
179 'build/c++11',
180 'build/deprecated',
181 'build/endif_comment',
182 'build/explicit_make_pair',
183 'build/forward_decl',
184 'build/header_guard',
185 'build/include',
186 'build/include_alpha',
187 'build/include_order',
188 'build/include_what_you_use',
189 'build/namespaces',
190 'build/printf_format',
191 'build/storage_class',
192 'legal/copyright',
193 'readability/alt_tokens',
194 'readability/braces',
195 'readability/casting',
196 'readability/check',
197 'readability/constructors',
198 'readability/fn_size',
199 'readability/function',
200 'readability/inheritance',
201 'readability/multiline_comment',
202 'readability/multiline_string',
203 'readability/namespace',
204 'readability/nolint',
205 'readability/nul',
206 'readability/strings',
207 'readability/todo',
208 'readability/utf8',
209 'runtime/arrays',
210 'runtime/casting',
211 'runtime/explicit',
212 'runtime/int',
213 'runtime/init',
214 'runtime/invalid_increment',
215 'runtime/member_string_references',
216 'runtime/memset',
217 'runtime/indentation_namespace',
218 'runtime/operator',
219 'runtime/printf',
220 'runtime/printf_format',
221 'runtime/references',
222 'runtime/string',
223 'runtime/threadsafe_fn',
224 'runtime/vlog',
225 'whitespace/blank_line',
226 'whitespace/braces',
227 'whitespace/comma',
228 'whitespace/comments',
229 'whitespace/empty_conditional_body',
230 'whitespace/empty_loop_body',
231 'whitespace/end_of_line',
232 'whitespace/ending_newline',
233 'whitespace/forcolon',
234 'whitespace/indent',
235 'whitespace/line_length',
236 'whitespace/newline',
237 'whitespace/operators',
238 'whitespace/parens',
239 'whitespace/semicolon',
240 'whitespace/tab',
241 'whitespace/todo',
242 ]
243
244# These error categories are no longer enforced by cpplint, but for backwards-
245# compatibility they may still appear in NOLINT comments.
246_LEGACY_ERROR_CATEGORIES = [
247 'readability/streams',
248 ]
erg@google.com6317a9c2009-06-25 00:28:19 +0000249
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000250# The default state of the category filter. This is overridden by the --filter=
erg@google.com6317a9c2009-06-25 00:28:19 +0000251# flag. By default all errors are on, so only add here categories that should be
252# off by default (i.e., categories that must be enabled by the --filter= flags).
253# All entries here should start with a '-' or '+', as in the --filter= flag.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000254_DEFAULT_FILTERS = ['-build/include_alpha']
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000255
256# We used to check for high-bit characters, but after much discussion we
257# decided those were OK, as long as they were in UTF-8 and didn't represent
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000258# hard-coded international strings, which belong in a separate i18n file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000259
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000260# C++ headers
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000261_CPP_HEADERS = frozenset([
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000262 # Legacy
263 'algobase.h',
264 'algo.h',
265 'alloc.h',
266 'builtinbuf.h',
267 'bvector.h',
268 'complex.h',
269 'defalloc.h',
270 'deque.h',
271 'editbuf.h',
272 'fstream.h',
273 'function.h',
274 'hash_map',
275 'hash_map.h',
276 'hash_set',
277 'hash_set.h',
278 'hashtable.h',
279 'heap.h',
280 'indstream.h',
281 'iomanip.h',
282 'iostream.h',
283 'istream.h',
284 'iterator.h',
285 'list.h',
286 'map.h',
287 'multimap.h',
288 'multiset.h',
289 'ostream.h',
290 'pair.h',
291 'parsestream.h',
292 'pfstream.h',
293 'procbuf.h',
294 'pthread_alloc',
295 'pthread_alloc.h',
296 'rope',
297 'rope.h',
298 'ropeimpl.h',
299 'set.h',
300 'slist',
301 'slist.h',
302 'stack.h',
303 'stdiostream.h',
304 'stl_alloc.h',
305 'stl_relops.h',
306 'streambuf.h',
307 'stream.h',
308 'strfile.h',
309 'strstream.h',
310 'tempbuf.h',
311 'tree.h',
312 'type_traits.h',
313 'vector.h',
314 # 17.6.1.2 C++ library headers
315 'algorithm',
316 'array',
317 'atomic',
318 'bitset',
319 'chrono',
320 'codecvt',
321 'complex',
322 'condition_variable',
323 'deque',
324 'exception',
325 'forward_list',
326 'fstream',
327 'functional',
328 'future',
329 'initializer_list',
330 'iomanip',
331 'ios',
332 'iosfwd',
333 'iostream',
334 'istream',
335 'iterator',
336 'limits',
337 'list',
338 'locale',
339 'map',
340 'memory',
341 'mutex',
342 'new',
343 'numeric',
344 'ostream',
345 'queue',
346 'random',
347 'ratio',
348 'regex',
349 'set',
350 'sstream',
351 'stack',
352 'stdexcept',
353 'streambuf',
354 'string',
355 'strstream',
356 'system_error',
357 'thread',
358 'tuple',
359 'typeindex',
360 'typeinfo',
361 'type_traits',
362 'unordered_map',
363 'unordered_set',
364 'utility',
365 'valarray',
366 'vector',
367 # 17.6.1.2 C++ headers for C library facilities
368 'cassert',
369 'ccomplex',
370 'cctype',
371 'cerrno',
372 'cfenv',
373 'cfloat',
374 'cinttypes',
375 'ciso646',
376 'climits',
377 'clocale',
378 'cmath',
379 'csetjmp',
380 'csignal',
381 'cstdalign',
382 'cstdarg',
383 'cstdbool',
384 'cstddef',
385 'cstdint',
386 'cstdio',
387 'cstdlib',
388 'cstring',
389 'ctgmath',
390 'ctime',
391 'cuchar',
392 'cwchar',
393 'cwctype',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000394 ])
395
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000396
avakulenko@google.com59146752014-08-11 20:20:55 +0000397# These headers are excluded from [build/include] and [build/include_order]
398# checks:
399# - Anything not following google file name conventions (containing an
400# uppercase character, such as Python.h or nsStringAPI.h, for example).
401# - Lua headers.
402_THIRD_PARTY_HEADERS_PATTERN = re.compile(
403 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
404
405
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000406# Assertion macros. These are defined in base/logging.h and
407# testing/base/gunit.h. Note that the _M versions need to come first
408# for substring matching to work.
409_CHECK_MACROS = [
erg@google.com6317a9c2009-06-25 00:28:19 +0000410 'DCHECK', 'CHECK',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000411 'EXPECT_TRUE_M', 'EXPECT_TRUE',
412 'ASSERT_TRUE_M', 'ASSERT_TRUE',
413 'EXPECT_FALSE_M', 'EXPECT_FALSE',
414 'ASSERT_FALSE_M', 'ASSERT_FALSE',
415 ]
416
erg@google.com6317a9c2009-06-25 00:28:19 +0000417# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000418_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
419
420for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
421 ('>=', 'GE'), ('>', 'GT'),
422 ('<=', 'LE'), ('<', 'LT')]:
erg@google.com6317a9c2009-06-25 00:28:19 +0000423 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000424 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
425 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
426 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
427 _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
428 _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
429
430for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
431 ('>=', 'LT'), ('>', 'LE'),
432 ('<=', 'GT'), ('<', 'GE')]:
433 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
434 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
435 _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
436 _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
437
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000438# Alternative tokens and their replacements. For full list, see section 2.5
439# Alternative tokens [lex.digraph] in the C++ standard.
440#
441# Digraphs (such as '%:') are not included here since it's a mess to
442# match those on a word boundary.
443_ALT_TOKEN_REPLACEMENT = {
444 'and': '&&',
445 'bitor': '|',
446 'or': '||',
447 'xor': '^',
448 'compl': '~',
449 'bitand': '&',
450 'and_eq': '&=',
451 'or_eq': '|=',
452 'xor_eq': '^=',
453 'not': '!',
454 'not_eq': '!='
455 }
456
457# Compile regular expression that matches all the above keywords. The "[ =()]"
458# bit is meant to avoid matching these keywords outside of boolean expressions.
459#
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000460# False positives include C-style multi-line comments and multi-line strings
461# but those have always been troublesome for cpplint.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000462_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
463 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
464
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000465
466# These constants define types of headers for use with
467# _IncludeState.CheckNextIncludeOrder().
468_C_SYS_HEADER = 1
469_CPP_SYS_HEADER = 2
470_LIKELY_MY_HEADER = 3
471_POSSIBLE_MY_HEADER = 4
472_OTHER_HEADER = 5
473
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000474# These constants define the current inline assembly state
475_NO_ASM = 0 # Outside of inline assembly block
476_INSIDE_ASM = 1 # Inside inline assembly block
477_END_ASM = 2 # Last line of inline assembly block
478_BLOCK_ASM = 3 # The whole block is an inline assembly block
479
480# Match start of assembly blocks
481_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
482 r'(?:\s+(volatile|__volatile__))?'
483 r'\s*[{(]')
484
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000485
486_regexp_compile_cache = {}
487
erg@google.com35589e62010-11-17 18:58:16 +0000488# {str, set(int)}: a map from error categories to sets of linenumbers
489# on which those errors are expected and should be suppressed.
490_error_suppressions = {}
491
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000492# The root directory used for deriving header guard CPP variable.
493# This is set by --root flag.
494_root = None
495
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000496# The allowed line length of files.
497# This is set by --linelength flag.
498_line_length = 80
499
500# The allowed extensions for file names
501# This is set by --extensions flag.
502_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
503
erg@google.com35589e62010-11-17 18:58:16 +0000504def ParseNolintSuppressions(filename, raw_line, linenum, error):
505 """Updates the global list of error-suppressions.
506
507 Parses any NOLINT comments on the current line, updating the global
508 error_suppressions store. Reports an error if the NOLINT comment
509 was malformed.
510
511 Args:
512 filename: str, the name of the input file.
513 raw_line: str, the line of input text, with comments.
514 linenum: int, the number of the current line.
515 error: function, an error handler.
516 """
avakulenko@google.com59146752014-08-11 20:20:55 +0000517 matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000518 if matched:
avakulenko@google.com59146752014-08-11 20:20:55 +0000519 if matched.group(1):
520 suppressed_line = linenum + 1
521 else:
522 suppressed_line = linenum
523 category = matched.group(2)
erg@google.com35589e62010-11-17 18:58:16 +0000524 if category in (None, '(*)'): # => "suppress all"
avakulenko@google.com59146752014-08-11 20:20:55 +0000525 _error_suppressions.setdefault(None, set()).add(suppressed_line)
erg@google.com35589e62010-11-17 18:58:16 +0000526 else:
527 if category.startswith('(') and category.endswith(')'):
528 category = category[1:-1]
529 if category in _ERROR_CATEGORIES:
avakulenko@google.com59146752014-08-11 20:20:55 +0000530 _error_suppressions.setdefault(category, set()).add(suppressed_line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000531 elif category not in _LEGACY_ERROR_CATEGORIES:
erg@google.com35589e62010-11-17 18:58:16 +0000532 error(filename, linenum, 'readability/nolint', 5,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000533 'Unknown NOLINT error category: %s' % category)
erg@google.com35589e62010-11-17 18:58:16 +0000534
535
536def ResetNolintSuppressions():
avakulenko@google.com59146752014-08-11 20:20:55 +0000537 """Resets the set of NOLINT suppressions to empty."""
erg@google.com35589e62010-11-17 18:58:16 +0000538 _error_suppressions.clear()
539
540
541def IsErrorSuppressedByNolint(category, linenum):
542 """Returns true if the specified error category is suppressed on this line.
543
544 Consults the global error_suppressions map populated by
545 ParseNolintSuppressions/ResetNolintSuppressions.
546
547 Args:
548 category: str, the category of the error.
549 linenum: int, the current line number.
550 Returns:
551 bool, True iff the error should be suppressed due to a NOLINT comment.
552 """
553 return (linenum in _error_suppressions.get(category, set()) or
554 linenum in _error_suppressions.get(None, set()))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000555
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000556
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000557def Match(pattern, s):
558 """Matches the string with the pattern, caching the compiled regexp."""
559 # The regexp compilation caching is inlined in both Match and Search for
560 # performance reasons; factoring it out into a separate function turns out
561 # to be noticeably expensive.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000562 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000563 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
564 return _regexp_compile_cache[pattern].match(s)
565
566
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000567def ReplaceAll(pattern, rep, s):
568 """Replaces instances of pattern in a string with a replacement.
569
570 The compiled regex is kept in a cache shared by Match and Search.
571
572 Args:
573 pattern: regex pattern
574 rep: replacement text
575 s: search string
576
577 Returns:
578 string with replacements made (or original string if no replacements)
579 """
580 if pattern not in _regexp_compile_cache:
581 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
582 return _regexp_compile_cache[pattern].sub(rep, s)
583
584
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000585def Search(pattern, s):
586 """Searches the string for the pattern, caching the compiled regexp."""
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000587 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000588 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
589 return _regexp_compile_cache[pattern].search(s)
590
591
avakulenko@google.com59146752014-08-11 20:20:55 +0000592class _IncludeState(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000593 """Tracks line numbers for includes, and the order in which includes appear.
594
avakulenko@google.com59146752014-08-11 20:20:55 +0000595 include_list contains list of lists of (header, line number) pairs.
596 It's a lists of lists rather than just one flat list to make it
597 easier to update across preprocessor boundaries.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000598
599 Call CheckNextIncludeOrder() once for each header in the file, passing
600 in the type constants defined above. Calls in an illegal order will
601 raise an _IncludeError with an appropriate error message.
602
603 """
604 # self._section will move monotonically through this set. If it ever
605 # needs to move backwards, CheckNextIncludeOrder will raise an error.
606 _INITIAL_SECTION = 0
607 _MY_H_SECTION = 1
608 _C_SECTION = 2
609 _CPP_SECTION = 3
610 _OTHER_H_SECTION = 4
611
612 _TYPE_NAMES = {
613 _C_SYS_HEADER: 'C system header',
614 _CPP_SYS_HEADER: 'C++ system header',
615 _LIKELY_MY_HEADER: 'header this file implements',
616 _POSSIBLE_MY_HEADER: 'header this file may implement',
617 _OTHER_HEADER: 'other header',
618 }
619 _SECTION_NAMES = {
620 _INITIAL_SECTION: "... nothing. (This can't be an error.)",
621 _MY_H_SECTION: 'a header this file implements',
622 _C_SECTION: 'C system header',
623 _CPP_SECTION: 'C++ system header',
624 _OTHER_H_SECTION: 'other header',
625 }
626
627 def __init__(self):
avakulenko@google.com59146752014-08-11 20:20:55 +0000628 self.include_list = [[]]
629 self.ResetSection('')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000630
avakulenko@google.com59146752014-08-11 20:20:55 +0000631 def FindHeader(self, header):
632 """Check if a header has already been included.
633
634 Args:
635 header: header to check.
636 Returns:
637 Line number of previous occurrence, or -1 if the header has not
638 been seen before.
639 """
640 for section_list in self.include_list:
641 for f in section_list:
642 if f[0] == header:
643 return f[1]
644 return -1
645
646 def ResetSection(self, directive):
647 """Reset section checking for preprocessor directive.
648
649 Args:
650 directive: preprocessor directive (e.g. "if", "else").
651 """
erg@google.com26970fa2009-11-17 18:07:32 +0000652 # The name of the current section.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000653 self._section = self._INITIAL_SECTION
erg@google.com26970fa2009-11-17 18:07:32 +0000654 # The path of last found header.
655 self._last_header = ''
656
avakulenko@google.com59146752014-08-11 20:20:55 +0000657 # Update list of includes. Note that we never pop from the
658 # include list.
659 if directive in ('if', 'ifdef', 'ifndef'):
660 self.include_list.append([])
661 elif directive in ('else', 'elif'):
662 self.include_list[-1] = []
663
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000664 def SetLastHeader(self, header_path):
665 self._last_header = header_path
666
erg@google.com26970fa2009-11-17 18:07:32 +0000667 def CanonicalizeAlphabeticalOrder(self, header_path):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000668 """Returns a path canonicalized for alphabetical comparison.
erg@google.com26970fa2009-11-17 18:07:32 +0000669
670 - replaces "-" with "_" so they both cmp the same.
671 - removes '-inl' since we don't require them to be after the main header.
672 - lowercase everything, just in case.
673
674 Args:
675 header_path: Path to be canonicalized.
676
677 Returns:
678 Canonicalized path.
679 """
680 return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
681
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000682 def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
erg@google.com26970fa2009-11-17 18:07:32 +0000683 """Check if a header is in alphabetical order with the previous header.
684
685 Args:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000686 clean_lines: A CleansedLines instance containing the file.
687 linenum: The number of the line to check.
688 header_path: Canonicalized header to be checked.
erg@google.com26970fa2009-11-17 18:07:32 +0000689
690 Returns:
691 Returns true if the header is in alphabetical order.
692 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000693 # If previous section is different from current section, _last_header will
694 # be reset to empty string, so it's always less than current header.
695 #
696 # If previous line was a blank line, assume that the headers are
697 # intentionally sorted the way they are.
698 if (self._last_header > header_path and
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000699 Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
erg@google.com26970fa2009-11-17 18:07:32 +0000700 return False
erg@google.com26970fa2009-11-17 18:07:32 +0000701 return True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000702
703 def CheckNextIncludeOrder(self, header_type):
704 """Returns a non-empty error message if the next header is out of order.
705
706 This function also updates the internal state to be ready to check
707 the next include.
708
709 Args:
710 header_type: One of the _XXX_HEADER constants defined above.
711
712 Returns:
713 The empty string if the header is in the right order, or an
714 error message describing what's wrong.
715
716 """
717 error_message = ('Found %s after %s' %
718 (self._TYPE_NAMES[header_type],
719 self._SECTION_NAMES[self._section]))
720
erg@google.com26970fa2009-11-17 18:07:32 +0000721 last_section = self._section
722
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000723 if header_type == _C_SYS_HEADER:
724 if self._section <= self._C_SECTION:
725 self._section = self._C_SECTION
726 else:
erg@google.com26970fa2009-11-17 18:07:32 +0000727 self._last_header = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000728 return error_message
729 elif header_type == _CPP_SYS_HEADER:
730 if self._section <= self._CPP_SECTION:
731 self._section = self._CPP_SECTION
732 else:
erg@google.com26970fa2009-11-17 18:07:32 +0000733 self._last_header = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000734 return error_message
735 elif header_type == _LIKELY_MY_HEADER:
736 if self._section <= self._MY_H_SECTION:
737 self._section = self._MY_H_SECTION
738 else:
739 self._section = self._OTHER_H_SECTION
740 elif header_type == _POSSIBLE_MY_HEADER:
741 if self._section <= self._MY_H_SECTION:
742 self._section = self._MY_H_SECTION
743 else:
744 # This will always be the fallback because we're not sure
745 # enough that the header is associated with this file.
746 self._section = self._OTHER_H_SECTION
747 else:
748 assert header_type == _OTHER_HEADER
749 self._section = self._OTHER_H_SECTION
750
erg@google.com26970fa2009-11-17 18:07:32 +0000751 if last_section != self._section:
752 self._last_header = ''
753
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000754 return ''
755
756
757class _CppLintState(object):
758 """Maintains module-wide state.."""
759
760 def __init__(self):
761 self.verbose_level = 1 # global setting.
762 self.error_count = 0 # global count of reported errors
erg@google.com6317a9c2009-06-25 00:28:19 +0000763 # filters to apply when emitting error messages
764 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000765 # backup of filter list. Used to restore the state after each file.
766 self._filters_backup = self.filters[:]
erg@google.com26970fa2009-11-17 18:07:32 +0000767 self.counting = 'total' # In what way are we counting errors?
768 self.errors_by_category = {} # string to int dict storing error counts
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000769
770 # output format:
771 # "emacs" - format that emacs can parse (default)
772 # "vs7" - format that Microsoft Visual Studio 7 can parse
773 self.output_format = 'emacs'
774
775 def SetOutputFormat(self, output_format):
776 """Sets the output format for errors."""
777 self.output_format = output_format
778
779 def SetVerboseLevel(self, level):
780 """Sets the module's verbosity, and returns the previous setting."""
781 last_verbose_level = self.verbose_level
782 self.verbose_level = level
783 return last_verbose_level
784
erg@google.com26970fa2009-11-17 18:07:32 +0000785 def SetCountingStyle(self, counting_style):
786 """Sets the module's counting options."""
787 self.counting = counting_style
788
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000789 def SetFilters(self, filters):
790 """Sets the error-message filters.
791
792 These filters are applied when deciding whether to emit a given
793 error message.
794
795 Args:
796 filters: A string of comma-separated filters (eg "+whitespace/indent").
797 Each filter should start with + or -; else we die.
erg@google.com6317a9c2009-06-25 00:28:19 +0000798
799 Raises:
800 ValueError: The comma-separated filters did not all start with '+' or '-'.
801 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000802 """
erg@google.com6317a9c2009-06-25 00:28:19 +0000803 # Default filters always have less priority than the flag ones.
804 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000805 self.AddFilters(filters)
806
807 def AddFilters(self, filters):
808 """ Adds more filters to the existing list of error-message filters. """
erg@google.com6317a9c2009-06-25 00:28:19 +0000809 for filt in filters.split(','):
810 clean_filt = filt.strip()
811 if clean_filt:
812 self.filters.append(clean_filt)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000813 for filt in self.filters:
814 if not (filt.startswith('+') or filt.startswith('-')):
815 raise ValueError('Every filter in --filters must start with + or -'
816 ' (%s does not)' % filt)
817
avakulenko@google.com17449932014-07-28 22:13:33 +0000818 def BackupFilters(self):
819 """ Saves the current filter list to backup storage."""
820 self._filters_backup = self.filters[:]
821
822 def RestoreFilters(self):
823 """ Restores filters previously backed up."""
824 self.filters = self._filters_backup[:]
825
erg@google.com26970fa2009-11-17 18:07:32 +0000826 def ResetErrorCounts(self):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000827 """Sets the module's error statistic back to zero."""
828 self.error_count = 0
erg@google.com26970fa2009-11-17 18:07:32 +0000829 self.errors_by_category = {}
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000830
erg@google.com26970fa2009-11-17 18:07:32 +0000831 def IncrementErrorCount(self, category):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000832 """Bumps the module's error statistic."""
833 self.error_count += 1
erg@google.com26970fa2009-11-17 18:07:32 +0000834 if self.counting in ('toplevel', 'detailed'):
835 if self.counting != 'detailed':
836 category = category.split('/')[0]
837 if category not in self.errors_by_category:
838 self.errors_by_category[category] = 0
839 self.errors_by_category[category] += 1
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000840
erg@google.com26970fa2009-11-17 18:07:32 +0000841 def PrintErrorCounts(self):
842 """Print a summary of errors by category, and the total."""
843 for category, count in self.errors_by_category.iteritems():
844 sys.stderr.write('Category \'%s\' errors found: %d\n' %
845 (category, count))
846 sys.stderr.write('Total errors found: %d\n' % self.error_count)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000847
848_cpplint_state = _CppLintState()
849
850
851def _OutputFormat():
852 """Gets the module's output format."""
853 return _cpplint_state.output_format
854
855
856def _SetOutputFormat(output_format):
857 """Sets the module's output format."""
858 _cpplint_state.SetOutputFormat(output_format)
859
860
861def _VerboseLevel():
862 """Returns the module's verbosity setting."""
863 return _cpplint_state.verbose_level
864
865
866def _SetVerboseLevel(level):
867 """Sets the module's verbosity, and returns the previous setting."""
868 return _cpplint_state.SetVerboseLevel(level)
869
870
erg@google.com26970fa2009-11-17 18:07:32 +0000871def _SetCountingStyle(level):
872 """Sets the module's counting options."""
873 _cpplint_state.SetCountingStyle(level)
874
875
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000876def _Filters():
877 """Returns the module's list of output filters, as a list."""
878 return _cpplint_state.filters
879
880
881def _SetFilters(filters):
882 """Sets the module's error-message filters.
883
884 These filters are applied when deciding whether to emit a given
885 error message.
886
887 Args:
888 filters: A string of comma-separated filters (eg "whitespace/indent").
889 Each filter should start with + or -; else we die.
890 """
891 _cpplint_state.SetFilters(filters)
892
avakulenko@google.com17449932014-07-28 22:13:33 +0000893def _AddFilters(filters):
894 """Adds more filter overrides.
avakulenko@google.com59146752014-08-11 20:20:55 +0000895
avakulenko@google.com17449932014-07-28 22:13:33 +0000896 Unlike _SetFilters, this function does not reset the current list of filters
897 available.
898
899 Args:
900 filters: A string of comma-separated filters (eg "whitespace/indent").
901 Each filter should start with + or -; else we die.
902 """
903 _cpplint_state.AddFilters(filters)
904
905def _BackupFilters():
906 """ Saves the current filter list to backup storage."""
907 _cpplint_state.BackupFilters()
908
909def _RestoreFilters():
910 """ Restores filters previously backed up."""
911 _cpplint_state.RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000912
913class _FunctionState(object):
914 """Tracks current function name and the number of lines in its body."""
915
916 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
917 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
918
919 def __init__(self):
920 self.in_a_function = False
921 self.lines_in_function = 0
922 self.current_function = ''
923
924 def Begin(self, function_name):
925 """Start analyzing function body.
926
927 Args:
928 function_name: The name of the function being tracked.
929 """
930 self.in_a_function = True
931 self.lines_in_function = 0
932 self.current_function = function_name
933
934 def Count(self):
935 """Count line in current function body."""
936 if self.in_a_function:
937 self.lines_in_function += 1
938
939 def Check(self, error, filename, linenum):
940 """Report if too many lines in function body.
941
942 Args:
943 error: The function to call with any errors found.
944 filename: The name of the current file.
945 linenum: The number of the line to check.
946 """
947 if Match(r'T(EST|est)', self.current_function):
948 base_trigger = self._TEST_TRIGGER
949 else:
950 base_trigger = self._NORMAL_TRIGGER
951 trigger = base_trigger * 2**_VerboseLevel()
952
953 if self.lines_in_function > trigger:
954 error_level = int(math.log(self.lines_in_function / base_trigger, 2))
955 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
956 if error_level > 5:
957 error_level = 5
958 error(filename, linenum, 'readability/fn_size', error_level,
959 'Small and focused functions are preferred:'
960 ' %s has %d non-comment lines'
961 ' (error triggered by exceeding %d lines).' % (
962 self.current_function, self.lines_in_function, trigger))
963
964 def End(self):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000965 """Stop analyzing function body."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000966 self.in_a_function = False
967
968
969class _IncludeError(Exception):
970 """Indicates a problem with the include order in a file."""
971 pass
972
973
avakulenko@google.com59146752014-08-11 20:20:55 +0000974class FileInfo(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000975 """Provides utility functions for filenames.
976
977 FileInfo provides easy access to the components of a file's path
978 relative to the project root.
979 """
980
981 def __init__(self, filename):
982 self._filename = filename
983
984 def FullName(self):
985 """Make Windows paths like Unix."""
986 return os.path.abspath(self._filename).replace('\\', '/')
987
988 def RepositoryName(self):
989 """FullName after removing the local path to the repository.
990
991 If we have a real absolute path name here we can try to do something smart:
992 detecting the root of the checkout and truncating /path/to/checkout from
993 the name so that we get header guards that don't include things like
994 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
995 people on different computers who have checked the source out to different
996 locations won't see bogus errors.
997 """
998 fullname = self.FullName()
999
1000 if os.path.exists(fullname):
1001 project_dir = os.path.dirname(fullname)
1002
1003 if os.path.exists(os.path.join(project_dir, ".svn")):
1004 # If there's a .svn file in the current directory, we recursively look
1005 # up the directory tree for the top of the SVN checkout
1006 root_dir = project_dir
1007 one_up_dir = os.path.dirname(root_dir)
1008 while os.path.exists(os.path.join(one_up_dir, ".svn")):
1009 root_dir = os.path.dirname(root_dir)
1010 one_up_dir = os.path.dirname(one_up_dir)
1011
1012 prefix = os.path.commonprefix([root_dir, project_dir])
1013 return fullname[len(prefix) + 1:]
1014
erg@chromium.org7956a872011-11-30 01:44:03 +00001015 # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
1016 # searching up from the current path.
sdefresne@chromium.org39628622016-04-21 17:00:21 +00001017 root_dir = current_dir = os.path.dirname(fullname)
1018 while current_dir != os.path.dirname(current_dir):
1019 if (os.path.exists(os.path.join(current_dir, ".git")) or
1020 os.path.exists(os.path.join(current_dir, ".hg")) or
1021 os.path.exists(os.path.join(current_dir, ".svn"))):
1022 root_dir = current_dir
1023 current_dir = os.path.dirname(current_dir)
erg@google.com35589e62010-11-17 18:58:16 +00001024
1025 if (os.path.exists(os.path.join(root_dir, ".git")) or
erg@chromium.org7956a872011-11-30 01:44:03 +00001026 os.path.exists(os.path.join(root_dir, ".hg")) or
1027 os.path.exists(os.path.join(root_dir, ".svn"))):
erg@google.com35589e62010-11-17 18:58:16 +00001028 prefix = os.path.commonprefix([root_dir, project_dir])
1029 return fullname[len(prefix) + 1:]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001030
1031 # Don't know what to do; header guard warnings may be wrong...
1032 return fullname
1033
1034 def Split(self):
1035 """Splits the file into the directory, basename, and extension.
1036
1037 For 'chrome/browser/browser.cc', Split() would
1038 return ('chrome/browser', 'browser', '.cc')
1039
1040 Returns:
1041 A tuple of (directory, basename, extension).
1042 """
1043
1044 googlename = self.RepositoryName()
1045 project, rest = os.path.split(googlename)
1046 return (project,) + os.path.splitext(rest)
1047
1048 def BaseName(self):
1049 """File base name - text after the final slash, before the final period."""
1050 return self.Split()[1]
1051
1052 def Extension(self):
1053 """File extension - text following the final period."""
1054 return self.Split()[2]
1055
1056 def NoExtension(self):
1057 """File has no source file extension."""
1058 return '/'.join(self.Split()[0:2])
1059
1060 def IsSource(self):
1061 """File has a source file extension."""
1062 return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
1063
1064
erg@google.com35589e62010-11-17 18:58:16 +00001065def _ShouldPrintError(category, confidence, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001066 """If confidence >= verbose, category passes filter and is not suppressed."""
erg@google.com35589e62010-11-17 18:58:16 +00001067
1068 # There are three ways we might decide not to print an error message:
1069 # a "NOLINT(category)" comment appears in the source,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001070 # the verbosity level isn't high enough, or the filters filter it out.
erg@google.com35589e62010-11-17 18:58:16 +00001071 if IsErrorSuppressedByNolint(category, linenum):
1072 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001073
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001074 if confidence < _cpplint_state.verbose_level:
1075 return False
1076
1077 is_filtered = False
1078 for one_filter in _Filters():
1079 if one_filter.startswith('-'):
1080 if category.startswith(one_filter[1:]):
1081 is_filtered = True
1082 elif one_filter.startswith('+'):
1083 if category.startswith(one_filter[1:]):
1084 is_filtered = False
1085 else:
1086 assert False # should have been checked for in SetFilter.
1087 if is_filtered:
1088 return False
1089
1090 return True
1091
1092
1093def Error(filename, linenum, category, confidence, message):
1094 """Logs the fact we've found a lint error.
1095
1096 We log where the error was found, and also our confidence in the error,
1097 that is, how certain we are this is a legitimate style regression, and
1098 not a misidentification or a use that's sometimes justified.
1099
erg@google.com35589e62010-11-17 18:58:16 +00001100 False positives can be suppressed by the use of
1101 "cpplint(category)" comments on the offending line. These are
1102 parsed into _error_suppressions.
1103
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001104 Args:
1105 filename: The name of the file containing the error.
1106 linenum: The number of the line containing the error.
1107 category: A string used to describe the "category" this bug
1108 falls under: "whitespace", say, or "runtime". Categories
1109 may have a hierarchy separated by slashes: "whitespace/indent".
1110 confidence: A number from 1-5 representing a confidence score for
1111 the error, with 5 meaning that we are certain of the problem,
1112 and 1 meaning that it could be a legitimate construct.
1113 message: The error message.
1114 """
erg@google.com35589e62010-11-17 18:58:16 +00001115 if _ShouldPrintError(category, confidence, linenum):
erg@google.com26970fa2009-11-17 18:07:32 +00001116 _cpplint_state.IncrementErrorCount(category)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001117 if _cpplint_state.output_format == 'vs7':
1118 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % (
1119 filename, linenum, message, category, confidence))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001120 elif _cpplint_state.output_format == 'eclipse':
1121 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % (
1122 filename, linenum, message, category, confidence))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001123 else:
1124 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % (
1125 filename, linenum, message, category, confidence))
1126
1127
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001128# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001129_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1130 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001131# Match a single C style comment on the same line.
1132_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
1133# Matches multi-line C style comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001134# This RE is a little bit more complicated than one might expect, because we
1135# have to take care of space removals tools so we can handle comments inside
1136# statements better.
1137# The current rule is: We only clear spaces from both sides when we're at the
1138# end of the line. Otherwise, we try to remove spaces from the right side,
1139# if this doesn't work we try on left side but only if there's a non-character
1140# on the right.
1141_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001142 r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
1143 _RE_PATTERN_C_COMMENTS + r'\s+|' +
1144 r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
1145 _RE_PATTERN_C_COMMENTS + r')')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001146
1147
1148def IsCppString(line):
1149 """Does line terminate so, that the next symbol is in string constant.
1150
1151 This function does not consider single-line nor multi-line comments.
1152
1153 Args:
1154 line: is a partial line of code starting from the 0..n.
1155
1156 Returns:
1157 True, if next character appended to 'line' is inside a
1158 string constant.
1159 """
1160
1161 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
1162 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
1163
1164
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001165def CleanseRawStrings(raw_lines):
1166 """Removes C++11 raw strings from lines.
1167
1168 Before:
1169 static const char kData[] = R"(
1170 multi-line string
1171 )";
1172
1173 After:
1174 static const char kData[] = ""
1175 (replaced by blank line)
1176 "";
1177
1178 Args:
1179 raw_lines: list of raw lines.
1180
1181 Returns:
1182 list of lines with C++11 raw strings replaced by empty strings.
1183 """
1184
1185 delimiter = None
1186 lines_without_raw_strings = []
1187 for line in raw_lines:
1188 if delimiter:
1189 # Inside a raw string, look for the end
1190 end = line.find(delimiter)
1191 if end >= 0:
1192 # Found the end of the string, match leading space for this
1193 # line and resume copying the original lines, and also insert
1194 # a "" on the last line.
1195 leading_space = Match(r'^(\s*)\S', line)
1196 line = leading_space.group(1) + '""' + line[end + len(delimiter):]
1197 delimiter = None
1198 else:
1199 # Haven't found the end yet, append a blank line.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001200 line = '""'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001201
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001202 # Look for beginning of a raw string, and replace them with
1203 # empty strings. This is done in a loop to handle multiple raw
1204 # strings on the same line.
1205 while delimiter is None:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001206 # Look for beginning of a raw string.
1207 # See 2.14.15 [lex.string] for syntax.
1208 matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1209 if matched:
1210 delimiter = ')' + matched.group(2) + '"'
1211
1212 end = matched.group(3).find(delimiter)
1213 if end >= 0:
1214 # Raw string ended on same line
1215 line = (matched.group(1) + '""' +
1216 matched.group(3)[end + len(delimiter):])
1217 delimiter = None
1218 else:
1219 # Start of a multi-line raw string
1220 line = matched.group(1) + '""'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001221 else:
1222 break
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001223
1224 lines_without_raw_strings.append(line)
1225
1226 # TODO(unknown): if delimiter is not None here, we might want to
1227 # emit a warning for unterminated string.
1228 return lines_without_raw_strings
1229
1230
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001231def FindNextMultiLineCommentStart(lines, lineix):
1232 """Find the beginning marker for a multiline comment."""
1233 while lineix < len(lines):
1234 if lines[lineix].strip().startswith('/*'):
1235 # Only return this marker if the comment goes beyond this line
1236 if lines[lineix].strip().find('*/', 2) < 0:
1237 return lineix
1238 lineix += 1
1239 return len(lines)
1240
1241
1242def FindNextMultiLineCommentEnd(lines, lineix):
1243 """We are inside a comment, find the end marker."""
1244 while lineix < len(lines):
1245 if lines[lineix].strip().endswith('*/'):
1246 return lineix
1247 lineix += 1
1248 return len(lines)
1249
1250
1251def RemoveMultiLineCommentsFromRange(lines, begin, end):
1252 """Clears a range of lines for multi-line comments."""
1253 # Having // dummy comments makes the lines non-empty, so we will not get
1254 # unnecessary blank line warnings later in the code.
1255 for i in range(begin, end):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001256 lines[i] = '/**/'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001257
1258
1259def RemoveMultiLineComments(filename, lines, error):
1260 """Removes multiline (c-style) comments from lines."""
1261 lineix = 0
1262 while lineix < len(lines):
1263 lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
1264 if lineix_begin >= len(lines):
1265 return
1266 lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
1267 if lineix_end >= len(lines):
1268 error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
1269 'Could not find end of multi-line comment')
1270 return
1271 RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
1272 lineix = lineix_end + 1
1273
1274
1275def CleanseComments(line):
1276 """Removes //-comments and single-line C-style /* */ comments.
1277
1278 Args:
1279 line: A line of C++ source.
1280
1281 Returns:
1282 The line with single-line comments removed.
1283 """
1284 commentpos = line.find('//')
1285 if commentpos != -1 and not IsCppString(line[:commentpos]):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001286 line = line[:commentpos].rstrip()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001287 # get rid of /* ... */
1288 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
1289
1290
erg@google.com6317a9c2009-06-25 00:28:19 +00001291class CleansedLines(object):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001292 """Holds 4 copies of all lines with different preprocessing applied to them.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001293
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001294 1) elided member contains lines without strings and comments.
1295 2) lines member contains lines without comments.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001296 3) raw_lines member contains all the lines without processing.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001297 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
1298 strings removed.
1299 All these members are of <type 'list'>, and of the same length.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001300 """
1301
1302 def __init__(self, lines):
1303 self.elided = []
1304 self.lines = []
1305 self.raw_lines = lines
1306 self.num_lines = len(lines)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001307 self.lines_without_raw_strings = CleanseRawStrings(lines)
1308 for linenum in range(len(self.lines_without_raw_strings)):
1309 self.lines.append(CleanseComments(
1310 self.lines_without_raw_strings[linenum]))
1311 elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001312 self.elided.append(CleanseComments(elided))
1313
1314 def NumLines(self):
1315 """Returns the number of lines represented."""
1316 return self.num_lines
1317
1318 @staticmethod
1319 def _CollapseStrings(elided):
1320 """Collapses strings and chars on a line to simple "" or '' blocks.
1321
1322 We nix strings first so we're not fooled by text like '"http://"'
1323
1324 Args:
1325 elided: The line being processed.
1326
1327 Returns:
1328 The line with collapsed strings.
1329 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001330 if _RE_PATTERN_INCLUDE.match(elided):
1331 return elided
1332
1333 # Remove escaped characters first to make quote/single quote collapsing
1334 # basic. Things that look like escaped characters shouldn't occur
1335 # outside of strings and chars.
1336 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
1337
1338 # Replace quoted strings and digit separators. Both single quotes
1339 # and double quotes are processed in the same loop, otherwise
1340 # nested quotes wouldn't work.
1341 collapsed = ''
1342 while True:
1343 # Find the first quote character
1344 match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
1345 if not match:
1346 collapsed += elided
1347 break
1348 head, quote, tail = match.groups()
1349
1350 if quote == '"':
1351 # Collapse double quoted strings
1352 second_quote = tail.find('"')
1353 if second_quote >= 0:
1354 collapsed += head + '""'
1355 elided = tail[second_quote + 1:]
1356 else:
1357 # Unmatched double quote, don't bother processing the rest
1358 # of the line since this is probably a multiline string.
1359 collapsed += elided
1360 break
1361 else:
1362 # Found single quote, check nearby text to eliminate digit separators.
1363 #
1364 # There is no special handling for floating point here, because
1365 # the integer/fractional/exponent parts would all be parsed
1366 # correctly as long as there are digits on both sides of the
1367 # separator. So we are fine as long as we don't see something
1368 # like "0.'3" (gcc 4.9.0 will not allow this literal).
1369 if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1370 match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
1371 collapsed += head + match_literal.group(1).replace("'", '')
1372 elided = match_literal.group(2)
1373 else:
1374 second_quote = tail.find('\'')
1375 if second_quote >= 0:
1376 collapsed += head + "''"
1377 elided = tail[second_quote + 1:]
1378 else:
1379 # Unmatched single quote
1380 collapsed += elided
1381 break
1382
1383 return collapsed
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001384
1385
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001386def FindEndOfExpressionInLine(line, startpos, stack):
1387 """Find the position just after the end of current parenthesized expression.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001388
1389 Args:
1390 line: a CleansedLines line.
1391 startpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001392 stack: nesting stack at startpos.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001393
1394 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001395 On finding matching end: (index just after matching end, None)
1396 On finding an unclosed expression: (-1, None)
1397 Otherwise: (-1, new stack at end of this line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001398 """
1399 for i in xrange(startpos, len(line)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001400 char = line[i]
1401 if char in '([{':
1402 # Found start of parenthesized expression, push to expression stack
1403 stack.append(char)
1404 elif char == '<':
1405 # Found potential start of template argument list
1406 if i > 0 and line[i - 1] == '<':
1407 # Left shift operator
1408 if stack and stack[-1] == '<':
1409 stack.pop()
1410 if not stack:
1411 return (-1, None)
1412 elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
1413 # operator<, don't add to stack
1414 continue
1415 else:
1416 # Tentative start of template argument list
1417 stack.append('<')
1418 elif char in ')]}':
1419 # Found end of parenthesized expression.
1420 #
1421 # If we are currently expecting a matching '>', the pending '<'
1422 # must have been an operator. Remove them from expression stack.
1423 while stack and stack[-1] == '<':
1424 stack.pop()
1425 if not stack:
1426 return (-1, None)
1427 if ((stack[-1] == '(' and char == ')') or
1428 (stack[-1] == '[' and char == ']') or
1429 (stack[-1] == '{' and char == '}')):
1430 stack.pop()
1431 if not stack:
1432 return (i + 1, None)
1433 else:
1434 # Mismatched parentheses
1435 return (-1, None)
1436 elif char == '>':
1437 # Found potential end of template argument list.
1438
1439 # Ignore "->" and operator functions
1440 if (i > 0 and
1441 (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
1442 continue
1443
1444 # Pop the stack if there is a matching '<'. Otherwise, ignore
1445 # this '>' since it must be an operator.
1446 if stack:
1447 if stack[-1] == '<':
1448 stack.pop()
1449 if not stack:
1450 return (i + 1, None)
1451 elif char == ';':
1452 # Found something that look like end of statements. If we are currently
1453 # expecting a '>', the matching '<' must have been an operator, since
1454 # template argument list should not contain statements.
1455 while stack and stack[-1] == '<':
1456 stack.pop()
1457 if not stack:
1458 return (-1, None)
1459
1460 # Did not find end of expression or unbalanced parentheses on this line
1461 return (-1, stack)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001462
1463
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001464def CloseExpression(clean_lines, linenum, pos):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001465 """If input points to ( or { or [ or <, finds the position that closes it.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001466
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001467 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001468 linenum/pos that correspond to the closing of the expression.
1469
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001470 TODO(unknown): cpplint spends a fair bit of time matching parentheses.
1471 Ideally we would want to index all opening and closing parentheses once
1472 and have CloseExpression be just a simple lookup, but due to preprocessor
1473 tricks, this is not so easy.
1474
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001475 Args:
1476 clean_lines: A CleansedLines instance containing the file.
1477 linenum: The number of the line to check.
1478 pos: A position on the line.
1479
1480 Returns:
1481 A tuple (line, linenum, pos) pointer *past* the closing brace, or
1482 (line, len(lines), -1) if we never find a close. Note we ignore
1483 strings and comments when matching; and the line we return is the
1484 'cleansed' line at linenum.
1485 """
1486
1487 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001488 if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001489 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001490
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001491 # Check first line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001492 (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001493 if end_pos > -1:
1494 return (line, linenum, end_pos)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001495
1496 # Continue scanning forward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001497 while stack and linenum < clean_lines.NumLines() - 1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001498 linenum += 1
1499 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001500 (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001501 if end_pos > -1:
1502 return (line, linenum, end_pos)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001503
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001504 # Did not find end of expression before end of file, give up
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001505 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001506
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001507
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001508def FindStartOfExpressionInLine(line, endpos, stack):
1509 """Find position at the matching start of current expression.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001510
1511 This is almost the reverse of FindEndOfExpressionInLine, but note
1512 that the input position and returned position differs by 1.
1513
1514 Args:
1515 line: a CleansedLines line.
1516 endpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001517 stack: nesting stack at endpos.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001518
1519 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001520 On finding matching start: (index at matching start, None)
1521 On finding an unclosed expression: (-1, None)
1522 Otherwise: (-1, new stack at beginning of this line)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001523 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001524 i = endpos
1525 while i >= 0:
1526 char = line[i]
1527 if char in ')]}':
1528 # Found end of expression, push to expression stack
1529 stack.append(char)
1530 elif char == '>':
1531 # Found potential end of template argument list.
1532 #
1533 # Ignore it if it's a "->" or ">=" or "operator>"
1534 if (i > 0 and
1535 (line[i - 1] == '-' or
1536 Match(r'\s>=\s', line[i - 1:]) or
1537 Search(r'\boperator\s*$', line[0:i]))):
1538 i -= 1
1539 else:
1540 stack.append('>')
1541 elif char == '<':
1542 # Found potential start of template argument list
1543 if i > 0 and line[i - 1] == '<':
1544 # Left shift operator
1545 i -= 1
1546 else:
1547 # If there is a matching '>', we can pop the expression stack.
1548 # Otherwise, ignore this '<' since it must be an operator.
1549 if stack and stack[-1] == '>':
1550 stack.pop()
1551 if not stack:
1552 return (i, None)
1553 elif char in '([{':
1554 # Found start of expression.
1555 #
1556 # If there are any unmatched '>' on the stack, they must be
1557 # operators. Remove those.
1558 while stack and stack[-1] == '>':
1559 stack.pop()
1560 if not stack:
1561 return (-1, None)
1562 if ((char == '(' and stack[-1] == ')') or
1563 (char == '[' and stack[-1] == ']') or
1564 (char == '{' and stack[-1] == '}')):
1565 stack.pop()
1566 if not stack:
1567 return (i, None)
1568 else:
1569 # Mismatched parentheses
1570 return (-1, None)
1571 elif char == ';':
1572 # Found something that look like end of statements. If we are currently
1573 # expecting a '<', the matching '>' must have been an operator, since
1574 # template argument list should not contain statements.
1575 while stack and stack[-1] == '>':
1576 stack.pop()
1577 if not stack:
1578 return (-1, None)
1579
1580 i -= 1
1581
1582 return (-1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001583
1584
1585def ReverseCloseExpression(clean_lines, linenum, pos):
1586 """If input points to ) or } or ] or >, finds the position that opens it.
1587
1588 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1589 linenum/pos that correspond to the opening of the expression.
1590
1591 Args:
1592 clean_lines: A CleansedLines instance containing the file.
1593 linenum: The number of the line to check.
1594 pos: A position on the line.
1595
1596 Returns:
1597 A tuple (line, linenum, pos) pointer *at* the opening brace, or
1598 (line, 0, -1) if we never find the matching opening brace. Note
1599 we ignore strings and comments when matching; and the line we
1600 return is the 'cleansed' line at linenum.
1601 """
1602 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001603 if line[pos] not in ')}]>':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001604 return (line, 0, -1)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001605
1606 # Check last line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001607 (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001608 if start_pos > -1:
1609 return (line, linenum, start_pos)
1610
1611 # Continue scanning backward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001612 while stack and linenum > 0:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001613 linenum -= 1
1614 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001615 (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001616 if start_pos > -1:
1617 return (line, linenum, start_pos)
1618
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001619 # Did not find start of expression before beginning of file, give up
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001620 return (line, 0, -1)
1621
1622
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001623def CheckForCopyright(filename, lines, error):
1624 """Logs an error if no Copyright message appears at the top of the file."""
1625
1626 # We'll say it should occur by line 10. Don't forget there's a
1627 # dummy line at the front.
1628 for line in xrange(1, min(len(lines), 11)):
1629 if re.search(r'Copyright', lines[line], re.I): break
1630 else: # means no copyright line was found
1631 error(filename, 0, 'legal/copyright', 5,
1632 'No copyright message found. '
1633 'You should have a line: "Copyright [year] <Copyright Owner>"')
1634
1635
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001636def GetIndentLevel(line):
1637 """Return the number of leading spaces in line.
1638
1639 Args:
1640 line: A string to check.
1641
1642 Returns:
1643 An integer count of leading spaces, possibly zero.
1644 """
1645 indent = Match(r'^( *)\S', line)
1646 if indent:
1647 return len(indent.group(1))
1648 else:
1649 return 0
1650
1651
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001652def GetHeaderGuardCPPVariable(filename):
1653 """Returns the CPP variable that should be used as a header guard.
1654
1655 Args:
1656 filename: The name of a C++ header file.
1657
1658 Returns:
1659 The CPP variable that should be used as a header guard in the
1660 named file.
1661
1662 """
1663
erg@google.com35589e62010-11-17 18:58:16 +00001664 # Restores original filename in case that cpplint is invoked from Emacs's
1665 # flymake.
1666 filename = re.sub(r'_flymake\.h$', '.h', filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001667 filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001668 # Replace 'c++' with 'cpp'.
1669 filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
skym@chromium.org3990c412016-02-05 20:55:12 +00001670
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001671 fileinfo = FileInfo(filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001672 file_path_from_root = fileinfo.RepositoryName()
1673 if _root:
1674 file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001675 return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001676
1677
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001678def CheckForHeaderGuard(filename, clean_lines, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001679 """Checks that the file contains a header guard.
1680
erg@google.com6317a9c2009-06-25 00:28:19 +00001681 Logs an error if no #ifndef header guard is present. For other
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001682 headers, checks that the full pathname is used.
1683
1684 Args:
1685 filename: The name of the C++ header file.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001686 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001687 error: The function to call with any errors found.
1688 """
1689
avakulenko@google.com59146752014-08-11 20:20:55 +00001690 # Don't check for header guards if there are error suppression
1691 # comments somewhere in this file.
1692 #
1693 # Because this is silencing a warning for a nonexistent line, we
1694 # only support the very specific NOLINT(build/header_guard) syntax,
1695 # and not the general NOLINT or NOLINT(*) syntax.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001696 raw_lines = clean_lines.lines_without_raw_strings
1697 for i in raw_lines:
avakulenko@google.com59146752014-08-11 20:20:55 +00001698 if Search(r'//\s*NOLINT\(build/header_guard\)', i):
1699 return
1700
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001701 cppvar = GetHeaderGuardCPPVariable(filename)
1702
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001703 ifndef = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001704 ifndef_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001705 define = ''
1706 endif = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001707 endif_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001708 for linenum, line in enumerate(raw_lines):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001709 linesplit = line.split()
1710 if len(linesplit) >= 2:
1711 # find the first occurrence of #ifndef and #define, save arg
1712 if not ifndef and linesplit[0] == '#ifndef':
1713 # set ifndef to the header guard presented on the #ifndef line.
1714 ifndef = linesplit[1]
1715 ifndef_linenum = linenum
1716 if not define and linesplit[0] == '#define':
1717 define = linesplit[1]
1718 # find the last occurrence of #endif, save entire line
1719 if line.startswith('#endif'):
1720 endif = line
1721 endif_linenum = linenum
1722
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001723 if not ifndef or not define or ifndef != define:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001724 error(filename, 0, 'build/header_guard', 5,
1725 'No #ifndef header guard found, suggested CPP variable is: %s' %
1726 cppvar)
1727 return
1728
1729 # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
1730 # for backward compatibility.
erg@google.com35589e62010-11-17 18:58:16 +00001731 if ifndef != cppvar:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001732 error_level = 0
1733 if ifndef != cppvar + '_':
1734 error_level = 5
1735
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001736 ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
erg@google.com35589e62010-11-17 18:58:16 +00001737 error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001738 error(filename, ifndef_linenum, 'build/header_guard', error_level,
1739 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1740
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001741 # Check for "//" comments on endif line.
1742 ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
1743 error)
1744 match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
1745 if match:
1746 if match.group(1) == '_':
1747 # Issue low severity warning for deprecated double trailing underscore
1748 error(filename, endif_linenum, 'build/header_guard', 0,
1749 '#endif line should be "#endif // %s"' % cppvar)
erg@chromium.orgc452fea2012-01-26 21:10:45 +00001750 return
1751
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001752 # Didn't find the corresponding "//" comment. If this file does not
1753 # contain any "//" comments at all, it could be that the compiler
1754 # only wants "/**/" comments, look for those instead.
1755 no_single_line_comments = True
1756 for i in xrange(1, len(raw_lines) - 1):
1757 line = raw_lines[i]
1758 if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
1759 no_single_line_comments = False
1760 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001761
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001762 if no_single_line_comments:
1763 match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
1764 if match:
1765 if match.group(1) == '_':
1766 # Low severity warning for double trailing underscore
1767 error(filename, endif_linenum, 'build/header_guard', 0,
1768 '#endif line should be "#endif /* %s */"' % cppvar)
1769 return
1770
1771 # Didn't find anything
1772 error(filename, endif_linenum, 'build/header_guard', 5,
1773 '#endif line should be "#endif // %s"' % cppvar)
1774
1775
1776def CheckHeaderFileIncluded(filename, include_state, error):
1777 """Logs an error if a .cc file does not include its header."""
1778
1779 # Do not check test files
1780 if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'):
1781 return
1782
1783 fileinfo = FileInfo(filename)
1784 headerfile = filename[0:len(filename) - 2] + 'h'
1785 if not os.path.exists(headerfile):
1786 return
1787 headername = FileInfo(headerfile).RepositoryName()
1788 first_include = 0
1789 for section_list in include_state.include_list:
1790 for f in section_list:
1791 if headername in f[0] or f[0] in headername:
1792 return
1793 if not first_include:
1794 first_include = f[1]
1795
1796 error(filename, first_include, 'build/include', 5,
1797 '%s should include its header file %s' % (fileinfo.RepositoryName(),
1798 headername))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001799
1800
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001801def CheckForBadCharacters(filename, lines, error):
1802 """Logs an error for each line containing bad characters.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001803
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001804 Two kinds of bad characters:
1805
1806 1. Unicode replacement characters: These indicate that either the file
1807 contained invalid UTF-8 (likely) or Unicode replacement characters (which
1808 it shouldn't). Note that it's possible for this to throw off line
1809 numbering if the invalid UTF-8 occurred adjacent to a newline.
1810
1811 2. NUL bytes. These are problematic for some tools.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001812
1813 Args:
1814 filename: The name of the current file.
1815 lines: An array of strings, each representing a line of the file.
1816 error: The function to call with any errors found.
1817 """
1818 for linenum, line in enumerate(lines):
1819 if u'\ufffd' in line:
1820 error(filename, linenum, 'readability/utf8', 5,
1821 'Line contains invalid UTF-8 (or Unicode replacement character).')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001822 if '\0' in line:
1823 error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001824
1825
1826def CheckForNewlineAtEOF(filename, lines, error):
1827 """Logs an error if there is no newline char at the end of the file.
1828
1829 Args:
1830 filename: The name of the current file.
1831 lines: An array of strings, each representing a line of the file.
1832 error: The function to call with any errors found.
1833 """
1834
1835 # The array lines() was created by adding two newlines to the
1836 # original file (go figure), then splitting on \n.
1837 # To verify that the file ends in \n, we just have to make sure the
1838 # last-but-two element of lines() exists and is empty.
1839 if len(lines) < 3 or lines[-2]:
1840 error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
1841 'Could not find a newline character at the end of the file.')
1842
1843
1844def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
1845 """Logs an error if we see /* ... */ or "..." that extend past one line.
1846
1847 /* ... */ comments are legit inside macros, for one line.
1848 Otherwise, we prefer // comments, so it's ok to warn about the
1849 other. Likewise, it's ok for strings to extend across multiple
1850 lines, as long as a line continuation character (backslash)
1851 terminates each line. Although not currently prohibited by the C++
1852 style guide, it's ugly and unnecessary. We don't do well with either
1853 in this lint program, so we warn about both.
1854
1855 Args:
1856 filename: The name of the current file.
1857 clean_lines: A CleansedLines instance containing the file.
1858 linenum: The number of the line to check.
1859 error: The function to call with any errors found.
1860 """
1861 line = clean_lines.elided[linenum]
1862
1863 # Remove all \\ (escaped backslashes) from the line. They are OK, and the
1864 # second (escaped) slash may trigger later \" detection erroneously.
1865 line = line.replace('\\\\', '')
1866
1867 if line.count('/*') > line.count('*/'):
1868 error(filename, linenum, 'readability/multiline_comment', 5,
1869 'Complex multi-line /*...*/-style comment found. '
1870 'Lint may give bogus warnings. '
1871 'Consider replacing these with //-style comments, '
1872 'with #if 0...#endif, '
1873 'or with more clearly structured multi-line comments.')
1874
1875 if (line.count('"') - line.count('\\"')) % 2:
1876 error(filename, linenum, 'readability/multiline_string', 5,
1877 'Multi-line string ("...") found. This lint script doesn\'t '
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001878 'do well with such strings, and may give bogus warnings. '
1879 'Use C++11 raw strings or concatenation instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001880
1881
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001882# (non-threadsafe name, thread-safe alternative, validation pattern)
1883#
1884# The validation pattern is used to eliminate false positives such as:
1885# _rand(); // false positive due to substring match.
1886# ->rand(); // some member function rand().
1887# ACMRandom rand(seed); // some variable named rand.
1888# ISAACRandom rand(); // another variable named rand.
1889#
1890# Basically we require the return value of these functions to be used
1891# in some expression context on the same line by matching on some
1892# operator before the function name. This eliminates constructors and
1893# member function calls.
1894_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
1895_THREADING_LIST = (
1896 ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
1897 ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
1898 ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
1899 ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
1900 ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
1901 ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
1902 ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
1903 ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
1904 ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
1905 ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
1906 ('strtok(', 'strtok_r(',
1907 _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
1908 ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001909 )
1910
1911
1912def CheckPosixThreading(filename, clean_lines, linenum, error):
1913 """Checks for calls to thread-unsafe functions.
1914
1915 Much code has been originally written without consideration of
1916 multi-threading. Also, engineers are relying on their old experience;
1917 they have learned posix before threading extensions were added. These
1918 tests guide the engineers to use thread-safe functions (when using
1919 posix directly).
1920
1921 Args:
1922 filename: The name of the current file.
1923 clean_lines: A CleansedLines instance containing the file.
1924 linenum: The number of the line to check.
1925 error: The function to call with any errors found.
1926 """
1927 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001928 for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
1929 # Additional pattern matching check to confirm that this is the
1930 # function we are looking for
1931 if Search(pattern, line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001932 error(filename, linenum, 'runtime/threadsafe_fn', 2,
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001933 'Consider using ' + multithread_safe_func +
1934 '...) instead of ' + single_thread_func +
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001935 '...) for improved thread safety.')
1936
1937
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001938def CheckVlogArguments(filename, clean_lines, linenum, error):
1939 """Checks that VLOG() is only used for defining a logging level.
1940
1941 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
1942 VLOG(FATAL) are not.
1943
1944 Args:
1945 filename: The name of the current file.
1946 clean_lines: A CleansedLines instance containing the file.
1947 linenum: The number of the line to check.
1948 error: The function to call with any errors found.
1949 """
1950 line = clean_lines.elided[linenum]
1951 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
1952 error(filename, linenum, 'runtime/vlog', 5,
1953 'VLOG() should be used with numeric verbosity level. '
1954 'Use LOG() if you want symbolic severity levels.')
1955
erg@google.com26970fa2009-11-17 18:07:32 +00001956# Matches invalid increment: *count++, which moves pointer instead of
erg@google.com6317a9c2009-06-25 00:28:19 +00001957# incrementing a value.
erg@google.com26970fa2009-11-17 18:07:32 +00001958_RE_PATTERN_INVALID_INCREMENT = re.compile(
erg@google.com6317a9c2009-06-25 00:28:19 +00001959 r'^\s*\*\w+(\+\+|--);')
1960
1961
1962def CheckInvalidIncrement(filename, clean_lines, linenum, error):
erg@google.com26970fa2009-11-17 18:07:32 +00001963 """Checks for invalid increment *count++.
erg@google.com6317a9c2009-06-25 00:28:19 +00001964
1965 For example following function:
1966 void increment_counter(int* count) {
1967 *count++;
1968 }
1969 is invalid, because it effectively does count++, moving pointer, and should
1970 be replaced with ++*count, (*count)++ or *count += 1.
1971
1972 Args:
1973 filename: The name of the current file.
1974 clean_lines: A CleansedLines instance containing the file.
1975 linenum: The number of the line to check.
1976 error: The function to call with any errors found.
1977 """
1978 line = clean_lines.elided[linenum]
erg@google.com26970fa2009-11-17 18:07:32 +00001979 if _RE_PATTERN_INVALID_INCREMENT.match(line):
erg@google.com6317a9c2009-06-25 00:28:19 +00001980 error(filename, linenum, 'runtime/invalid_increment', 5,
1981 'Changing pointer instead of value (or unused value of operator*).')
1982
1983
avakulenko@google.com59146752014-08-11 20:20:55 +00001984def IsMacroDefinition(clean_lines, linenum):
1985 if Search(r'^#define', clean_lines[linenum]):
1986 return True
1987
1988 if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
1989 return True
1990
1991 return False
1992
1993
1994def IsForwardClassDeclaration(clean_lines, linenum):
1995 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
1996
1997
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001998class _BlockInfo(object):
1999 """Stores information about a generic block of code."""
2000
2001 def __init__(self, seen_open_brace):
2002 self.seen_open_brace = seen_open_brace
2003 self.open_parentheses = 0
2004 self.inline_asm = _NO_ASM
avakulenko@google.com59146752014-08-11 20:20:55 +00002005 self.check_namespace_indentation = False
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002006
2007 def CheckBegin(self, filename, clean_lines, linenum, error):
2008 """Run checks that applies to text up to the opening brace.
2009
2010 This is mostly for checking the text after the class identifier
2011 and the "{", usually where the base class is specified. For other
2012 blocks, there isn't much to check, so we always pass.
2013
2014 Args:
2015 filename: The name of the current file.
2016 clean_lines: A CleansedLines instance containing the file.
2017 linenum: The number of the line to check.
2018 error: The function to call with any errors found.
2019 """
2020 pass
2021
2022 def CheckEnd(self, filename, clean_lines, linenum, error):
2023 """Run checks that applies to text after the closing brace.
2024
2025 This is mostly used for checking end of namespace comments.
2026
2027 Args:
2028 filename: The name of the current file.
2029 clean_lines: A CleansedLines instance containing the file.
2030 linenum: The number of the line to check.
2031 error: The function to call with any errors found.
2032 """
2033 pass
2034
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002035 def IsBlockInfo(self):
2036 """Returns true if this block is a _BlockInfo.
2037
2038 This is convenient for verifying that an object is an instance of
2039 a _BlockInfo, but not an instance of any of the derived classes.
2040
2041 Returns:
2042 True for this class, False for derived classes.
2043 """
2044 return self.__class__ == _BlockInfo
2045
2046
2047class _ExternCInfo(_BlockInfo):
2048 """Stores information about an 'extern "C"' block."""
2049
2050 def __init__(self):
2051 _BlockInfo.__init__(self, True)
2052
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002053
2054class _ClassInfo(_BlockInfo):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002055 """Stores information about a class."""
2056
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002057 def __init__(self, name, class_or_struct, clean_lines, linenum):
2058 _BlockInfo.__init__(self, False)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002059 self.name = name
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002060 self.starting_linenum = linenum
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002061 self.is_derived = False
avakulenko@google.com59146752014-08-11 20:20:55 +00002062 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002063 if class_or_struct == 'struct':
2064 self.access = 'public'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002065 self.is_struct = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002066 else:
2067 self.access = 'private'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002068 self.is_struct = False
2069
2070 # Remember initial indentation level for this class. Using raw_lines here
2071 # instead of elided to account for leading comments.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002072 self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002073
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002074 # Try to find the end of the class. This will be confused by things like:
2075 # class A {
2076 # } *x = { ...
2077 #
2078 # But it's still good enough for CheckSectionSpacing.
2079 self.last_line = 0
2080 depth = 0
2081 for i in range(linenum, clean_lines.NumLines()):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002082 line = clean_lines.elided[i]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002083 depth += line.count('{') - line.count('}')
2084 if not depth:
2085 self.last_line = i
2086 break
2087
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002088 def CheckBegin(self, filename, clean_lines, linenum, error):
2089 # Look for a bare ':'
2090 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2091 self.is_derived = True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002092
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002093 def CheckEnd(self, filename, clean_lines, linenum, error):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002094 # If there is a DISALLOW macro, it should appear near the end of
2095 # the class.
2096 seen_last_thing_in_class = False
2097 for i in xrange(linenum - 1, self.starting_linenum, -1):
2098 match = Search(
2099 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2100 self.name + r'\)',
2101 clean_lines.elided[i])
2102 if match:
2103 if seen_last_thing_in_class:
2104 error(filename, i, 'readability/constructors', 3,
2105 match.group(1) + ' should be the last thing in the class')
2106 break
2107
2108 if not Match(r'^\s*$', clean_lines.elided[i]):
2109 seen_last_thing_in_class = True
2110
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002111 # Check that closing brace is aligned with beginning of the class.
2112 # Only do this if the closing brace is indented by only whitespaces.
2113 # This means we will not check single-line class definitions.
2114 indent = Match(r'^( *)\}', clean_lines.elided[linenum])
2115 if indent and len(indent.group(1)) != self.class_indent:
2116 if self.is_struct:
2117 parent = 'struct ' + self.name
2118 else:
2119 parent = 'class ' + self.name
2120 error(filename, linenum, 'whitespace/indent', 3,
2121 'Closing brace should be aligned with beginning of %s' % parent)
2122
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002123
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002124class _NamespaceInfo(_BlockInfo):
2125 """Stores information about a namespace."""
2126
2127 def __init__(self, name, linenum):
2128 _BlockInfo.__init__(self, False)
2129 self.name = name or ''
2130 self.starting_linenum = linenum
avakulenko@google.com59146752014-08-11 20:20:55 +00002131 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002132
2133 def CheckEnd(self, filename, clean_lines, linenum, error):
2134 """Check end of namespace comments."""
2135 line = clean_lines.raw_lines[linenum]
2136
2137 # Check how many lines is enclosed in this namespace. Don't issue
2138 # warning for missing namespace comments if there aren't enough
2139 # lines. However, do apply checks if there is already an end of
2140 # namespace comment and it's incorrect.
2141 #
2142 # TODO(unknown): We always want to check end of namespace comments
2143 # if a namespace is large, but sometimes we also want to apply the
2144 # check if a short namespace contained nontrivial things (something
2145 # other than forward declarations). There is currently no logic on
2146 # deciding what these nontrivial things are, so this check is
2147 # triggered by namespace size only, which works most of the time.
2148 if (linenum - self.starting_linenum < 10
2149 and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)):
2150 return
2151
2152 # Look for matching comment at end of namespace.
2153 #
2154 # Note that we accept C style "/* */" comments for terminating
2155 # namespaces, so that code that terminate namespaces inside
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002156 # preprocessor macros can be cpplint clean.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002157 #
2158 # We also accept stuff like "// end of namespace <name>." with the
2159 # period at the end.
2160 #
2161 # Besides these, we don't accept anything else, otherwise we might
2162 # get false negatives when existing comment is a substring of the
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002163 # expected namespace.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002164 if self.name:
2165 # Named namespace
2166 if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
2167 r'[\*/\.\\\s]*$'),
2168 line):
2169 error(filename, linenum, 'readability/namespace', 5,
2170 'Namespace should be terminated with "// namespace %s"' %
2171 self.name)
2172 else:
2173 # Anonymous namespace
2174 if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002175 # If "// namespace anonymous" or "// anonymous namespace (more text)",
2176 # mention "// anonymous namespace" as an acceptable form
2177 if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
2178 error(filename, linenum, 'readability/namespace', 5,
2179 'Anonymous namespace should be terminated with "// namespace"'
2180 ' or "// anonymous namespace"')
2181 else:
2182 error(filename, linenum, 'readability/namespace', 5,
2183 'Anonymous namespace should be terminated with "// namespace"')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002184
2185
2186class _PreprocessorInfo(object):
2187 """Stores checkpoints of nesting stacks when #if/#else is seen."""
2188
2189 def __init__(self, stack_before_if):
2190 # The entire nesting stack before #if
2191 self.stack_before_if = stack_before_if
2192
2193 # The entire nesting stack up to #else
2194 self.stack_before_else = []
2195
2196 # Whether we have already seen #else or #elif
2197 self.seen_else = False
2198
2199
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002200class NestingState(object):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002201 """Holds states related to parsing braces."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002202
2203 def __init__(self):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002204 # Stack for tracking all braces. An object is pushed whenever we
2205 # see a "{", and popped when we see a "}". Only 3 types of
2206 # objects are possible:
2207 # - _ClassInfo: a class or struct.
2208 # - _NamespaceInfo: a namespace.
2209 # - _BlockInfo: some other type of block.
2210 self.stack = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002211
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002212 # Top of the previous stack before each Update().
2213 #
2214 # Because the nesting_stack is updated at the end of each line, we
2215 # had to do some convoluted checks to find out what is the current
2216 # scope at the beginning of the line. This check is simplified by
2217 # saving the previous top of nesting stack.
2218 #
2219 # We could save the full stack, but we only need the top. Copying
2220 # the full nesting stack would slow down cpplint by ~10%.
2221 self.previous_stack_top = []
2222
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002223 # Stack of _PreprocessorInfo objects.
2224 self.pp_stack = []
2225
2226 def SeenOpenBrace(self):
2227 """Check if we have seen the opening brace for the innermost block.
2228
2229 Returns:
2230 True if we have seen the opening brace, False if the innermost
2231 block is still expecting an opening brace.
2232 """
2233 return (not self.stack) or self.stack[-1].seen_open_brace
2234
2235 def InNamespaceBody(self):
2236 """Check if we are currently one level inside a namespace body.
2237
2238 Returns:
2239 True if top of the stack is a namespace block, False otherwise.
2240 """
2241 return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
2242
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002243 def InExternC(self):
2244 """Check if we are currently one level inside an 'extern "C"' block.
2245
2246 Returns:
2247 True if top of the stack is an extern block, False otherwise.
2248 """
2249 return self.stack and isinstance(self.stack[-1], _ExternCInfo)
2250
2251 def InClassDeclaration(self):
2252 """Check if we are currently one level inside a class or struct declaration.
2253
2254 Returns:
2255 True if top of the stack is a class/struct, False otherwise.
2256 """
2257 return self.stack and isinstance(self.stack[-1], _ClassInfo)
2258
2259 def InAsmBlock(self):
2260 """Check if we are currently one level inside an inline ASM block.
2261
2262 Returns:
2263 True if the top of the stack is a block containing inline ASM.
2264 """
2265 return self.stack and self.stack[-1].inline_asm != _NO_ASM
2266
2267 def InTemplateArgumentList(self, clean_lines, linenum, pos):
2268 """Check if current position is inside template argument list.
2269
2270 Args:
2271 clean_lines: A CleansedLines instance containing the file.
2272 linenum: The number of the line to check.
2273 pos: position just after the suspected template argument.
2274 Returns:
2275 True if (linenum, pos) is inside template arguments.
2276 """
2277 while linenum < clean_lines.NumLines():
2278 # Find the earliest character that might indicate a template argument
2279 line = clean_lines.elided[linenum]
2280 match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2281 if not match:
2282 linenum += 1
2283 pos = 0
2284 continue
2285 token = match.group(1)
2286 pos += len(match.group(0))
2287
2288 # These things do not look like template argument list:
2289 # class Suspect {
2290 # class Suspect x; }
2291 if token in ('{', '}', ';'): return False
2292
2293 # These things look like template argument list:
2294 # template <class Suspect>
2295 # template <class Suspect = default_value>
2296 # template <class Suspect[]>
2297 # template <class Suspect...>
2298 if token in ('>', '=', '[', ']', '.'): return True
2299
2300 # Check if token is an unmatched '<'.
2301 # If not, move on to the next character.
2302 if token != '<':
2303 pos += 1
2304 if pos >= len(line):
2305 linenum += 1
2306 pos = 0
2307 continue
2308
2309 # We can't be sure if we just find a single '<', and need to
2310 # find the matching '>'.
2311 (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
2312 if end_pos < 0:
2313 # Not sure if template argument list or syntax error in file
2314 return False
2315 linenum = end_line
2316 pos = end_pos
2317 return False
2318
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002319 def UpdatePreprocessor(self, line):
2320 """Update preprocessor stack.
2321
2322 We need to handle preprocessors due to classes like this:
2323 #ifdef SWIG
2324 struct ResultDetailsPageElementExtensionPoint {
2325 #else
2326 struct ResultDetailsPageElementExtensionPoint : public Extension {
2327 #endif
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002328
2329 We make the following assumptions (good enough for most files):
2330 - Preprocessor condition evaluates to true from #if up to first
2331 #else/#elif/#endif.
2332
2333 - Preprocessor condition evaluates to false from #else/#elif up
2334 to #endif. We still perform lint checks on these lines, but
2335 these do not affect nesting stack.
2336
2337 Args:
2338 line: current line to check.
2339 """
2340 if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2341 # Beginning of #if block, save the nesting stack here. The saved
2342 # stack will allow us to restore the parsing state in the #else case.
2343 self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
2344 elif Match(r'^\s*#\s*(else|elif)\b', line):
2345 # Beginning of #else block
2346 if self.pp_stack:
2347 if not self.pp_stack[-1].seen_else:
2348 # This is the first #else or #elif block. Remember the
2349 # whole nesting stack up to this point. This is what we
2350 # keep after the #endif.
2351 self.pp_stack[-1].seen_else = True
2352 self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
2353
2354 # Restore the stack to how it was before the #if
2355 self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
2356 else:
2357 # TODO(unknown): unexpected #else, issue warning?
2358 pass
2359 elif Match(r'^\s*#\s*endif\b', line):
2360 # End of #if or #else blocks.
2361 if self.pp_stack:
2362 # If we saw an #else, we will need to restore the nesting
2363 # stack to its former state before the #else, otherwise we
2364 # will just continue from where we left off.
2365 if self.pp_stack[-1].seen_else:
2366 # Here we can just use a shallow copy since we are the last
2367 # reference to it.
2368 self.stack = self.pp_stack[-1].stack_before_else
2369 # Drop the corresponding #if
2370 self.pp_stack.pop()
2371 else:
2372 # TODO(unknown): unexpected #endif, issue warning?
2373 pass
2374
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002375 # TODO(unknown): Update() is too long, but we will refactor later.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002376 def Update(self, filename, clean_lines, linenum, error):
2377 """Update nesting state with current line.
2378
2379 Args:
2380 filename: The name of the current file.
2381 clean_lines: A CleansedLines instance containing the file.
2382 linenum: The number of the line to check.
2383 error: The function to call with any errors found.
2384 """
2385 line = clean_lines.elided[linenum]
2386
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002387 # Remember top of the previous nesting stack.
2388 #
2389 # The stack is always pushed/popped and not modified in place, so
2390 # we can just do a shallow copy instead of copy.deepcopy. Using
2391 # deepcopy would slow down cpplint by ~28%.
2392 if self.stack:
2393 self.previous_stack_top = self.stack[-1]
2394 else:
2395 self.previous_stack_top = None
2396
2397 # Update pp_stack
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002398 self.UpdatePreprocessor(line)
2399
2400 # Count parentheses. This is to avoid adding struct arguments to
2401 # the nesting stack.
2402 if self.stack:
2403 inner_block = self.stack[-1]
2404 depth_change = line.count('(') - line.count(')')
2405 inner_block.open_parentheses += depth_change
2406
2407 # Also check if we are starting or ending an inline assembly block.
2408 if inner_block.inline_asm in (_NO_ASM, _END_ASM):
2409 if (depth_change != 0 and
2410 inner_block.open_parentheses == 1 and
2411 _MATCH_ASM.match(line)):
2412 # Enter assembly block
2413 inner_block.inline_asm = _INSIDE_ASM
2414 else:
2415 # Not entering assembly block. If previous line was _END_ASM,
2416 # we will now shift to _NO_ASM state.
2417 inner_block.inline_asm = _NO_ASM
2418 elif (inner_block.inline_asm == _INSIDE_ASM and
2419 inner_block.open_parentheses == 0):
2420 # Exit assembly block
2421 inner_block.inline_asm = _END_ASM
2422
2423 # Consume namespace declaration at the beginning of the line. Do
2424 # this in a loop so that we catch same line declarations like this:
2425 # namespace proto2 { namespace bridge { class MessageSet; } }
2426 while True:
2427 # Match start of namespace. The "\b\s*" below catches namespace
2428 # declarations even if it weren't followed by a whitespace, this
2429 # is so that we don't confuse our namespace checker. The
2430 # missing spaces will be flagged by CheckSpacing.
2431 namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2432 if not namespace_decl_match:
2433 break
2434
2435 new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
2436 self.stack.append(new_namespace)
2437
2438 line = namespace_decl_match.group(2)
2439 if line.find('{') != -1:
2440 new_namespace.seen_open_brace = True
2441 line = line[line.find('{') + 1:]
2442
2443 # Look for a class declaration in whatever is left of the line
2444 # after parsing namespaces. The regexp accounts for decorated classes
2445 # such as in:
2446 # class LOCKABLE API Object {
2447 # };
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002448 class_decl_match = Match(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002449 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
2450 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
2451 r'(.*)$', line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002452 if (class_decl_match and
2453 (not self.stack or self.stack[-1].open_parentheses == 0)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002454 # We do not want to accept classes that are actually template arguments:
2455 # template <class Ignore1,
2456 # class Ignore2 = Default<Args>,
2457 # template <Args> class Ignore3>
2458 # void Function() {};
2459 #
2460 # To avoid template argument cases, we scan forward and look for
2461 # an unmatched '>'. If we see one, assume we are inside a
2462 # template argument list.
2463 end_declaration = len(class_decl_match.group(1))
2464 if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
2465 self.stack.append(_ClassInfo(
2466 class_decl_match.group(3), class_decl_match.group(2),
2467 clean_lines, linenum))
2468 line = class_decl_match.group(4)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002469
2470 # If we have not yet seen the opening brace for the innermost block,
2471 # run checks here.
2472 if not self.SeenOpenBrace():
2473 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2474
2475 # Update access control if we are inside a class/struct
2476 if self.stack and isinstance(self.stack[-1], _ClassInfo):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002477 classinfo = self.stack[-1]
2478 access_match = Match(
2479 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
2480 r':(?:[^:]|$)',
2481 line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002482 if access_match:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002483 classinfo.access = access_match.group(2)
2484
2485 # Check that access keywords are indented +1 space. Skip this
2486 # check if the keywords are not preceded by whitespaces.
2487 indent = access_match.group(1)
2488 if (len(indent) != classinfo.class_indent + 1 and
2489 Match(r'^\s*$', indent)):
2490 if classinfo.is_struct:
2491 parent = 'struct ' + classinfo.name
2492 else:
2493 parent = 'class ' + classinfo.name
2494 slots = ''
2495 if access_match.group(3):
2496 slots = access_match.group(3)
2497 error(filename, linenum, 'whitespace/indent', 3,
2498 '%s%s: should be indented +1 space inside %s' % (
2499 access_match.group(2), slots, parent))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002500
2501 # Consume braces or semicolons from what's left of the line
2502 while True:
2503 # Match first brace, semicolon, or closed parenthesis.
2504 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
2505 if not matched:
2506 break
2507
2508 token = matched.group(1)
2509 if token == '{':
2510 # If namespace or class hasn't seen a opening brace yet, mark
2511 # namespace/class head as complete. Push a new block onto the
2512 # stack otherwise.
2513 if not self.SeenOpenBrace():
2514 self.stack[-1].seen_open_brace = True
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002515 elif Match(r'^extern\s*"[^"]*"\s*\{', line):
2516 self.stack.append(_ExternCInfo())
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002517 else:
2518 self.stack.append(_BlockInfo(True))
2519 if _MATCH_ASM.match(line):
2520 self.stack[-1].inline_asm = _BLOCK_ASM
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002521
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002522 elif token == ';' or token == ')':
2523 # If we haven't seen an opening brace yet, but we already saw
2524 # a semicolon, this is probably a forward declaration. Pop
2525 # the stack for these.
2526 #
2527 # Similarly, if we haven't seen an opening brace yet, but we
2528 # already saw a closing parenthesis, then these are probably
2529 # function arguments with extra "class" or "struct" keywords.
2530 # Also pop these stack for these.
2531 if not self.SeenOpenBrace():
2532 self.stack.pop()
2533 else: # token == '}'
2534 # Perform end of block checks and pop the stack.
2535 if self.stack:
2536 self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2537 self.stack.pop()
2538 line = matched.group(2)
2539
2540 def InnermostClass(self):
2541 """Get class info on the top of the stack.
2542
2543 Returns:
2544 A _ClassInfo object if we are inside a class, or None otherwise.
2545 """
2546 for i in range(len(self.stack), 0, -1):
2547 classinfo = self.stack[i - 1]
2548 if isinstance(classinfo, _ClassInfo):
2549 return classinfo
2550 return None
2551
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002552 def CheckCompletedBlocks(self, filename, error):
2553 """Checks that all classes and namespaces have been completely parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002554
2555 Call this when all lines in a file have been processed.
2556 Args:
2557 filename: The name of the current file.
2558 error: The function to call with any errors found.
2559 """
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002560 # Note: This test can result in false positives if #ifdef constructs
2561 # get in the way of brace matching. See the testBuildClass test in
2562 # cpplint_unittest.py for an example of this.
2563 for obj in self.stack:
2564 if isinstance(obj, _ClassInfo):
2565 error(filename, obj.starting_linenum, 'build/class', 5,
2566 'Failed to find complete declaration of class %s' %
2567 obj.name)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002568 elif isinstance(obj, _NamespaceInfo):
2569 error(filename, obj.starting_linenum, 'build/namespaces', 5,
2570 'Failed to find complete declaration of namespace %s' %
2571 obj.name)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002572
2573
2574def CheckForNonStandardConstructs(filename, clean_lines, linenum,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002575 nesting_state, error):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002576 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002577
2578 Complain about several constructs which gcc-2 accepts, but which are
2579 not standard C++. Warning about these in lint is one way to ease the
2580 transition to new compilers.
2581 - put storage class first (e.g. "static const" instead of "const static").
2582 - "%lld" instead of %qd" in printf-type functions.
2583 - "%1$d" is non-standard in printf-type functions.
2584 - "\%" is an undefined character escape sequence.
2585 - text after #endif is not allowed.
2586 - invalid inner-style forward declaration.
2587 - >? and <? operators, and their >?= and <?= cousins.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002588
erg@google.com26970fa2009-11-17 18:07:32 +00002589 Additionally, check for constructor/destructor style violations and reference
2590 members, as it is very convenient to do so while checking for
2591 gcc-2 compliance.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002592
2593 Args:
2594 filename: The name of the current file.
2595 clean_lines: A CleansedLines instance containing the file.
2596 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002597 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002598 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002599 error: A callable to which errors are reported, which takes 4 arguments:
2600 filename, line number, error level, and message
2601 """
2602
2603 # Remove comments from the line, but leave in strings for now.
2604 line = clean_lines.lines[linenum]
2605
2606 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2607 error(filename, linenum, 'runtime/printf_format', 3,
2608 '%q in format strings is deprecated. Use %ll instead.')
2609
2610 if Search(r'printf\s*\(.*".*%\d+\$', line):
2611 error(filename, linenum, 'runtime/printf_format', 2,
2612 '%N$ formats are unconventional. Try rewriting to avoid them.')
2613
2614 # Remove escaped backslashes before looking for undefined escapes.
2615 line = line.replace('\\\\', '')
2616
2617 if Search(r'("|\').*\\(%|\[|\(|{)', line):
2618 error(filename, linenum, 'build/printf_format', 3,
2619 '%, [, (, and { are undefined character escapes. Unescape them.')
2620
2621 # For the rest, work with both comments and strings removed.
2622 line = clean_lines.elided[linenum]
2623
2624 if Search(r'\b(const|volatile|void|char|short|int|long'
2625 r'|float|double|signed|unsigned'
2626 r'|schar|u?int8|u?int16|u?int32|u?int64)'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002627 r'\s+(register|static|extern|typedef)\b',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002628 line):
2629 error(filename, linenum, 'build/storage_class', 5,
2630 'Storage class (static, extern, typedef, etc) should be first.')
2631
2632 if Match(r'\s*#\s*endif\s*[^/\s]+', line):
2633 error(filename, linenum, 'build/endif_comment', 5,
2634 'Uncommented text after #endif is non-standard. Use a comment.')
2635
2636 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2637 error(filename, linenum, 'build/forward_decl', 5,
2638 'Inner-style forward declarations are invalid. Remove this line.')
2639
2640 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2641 line):
2642 error(filename, linenum, 'build/deprecated', 3,
2643 '>? and <? (max and min) operators are non-standard and deprecated.')
2644
erg@google.com26970fa2009-11-17 18:07:32 +00002645 if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2646 # TODO(unknown): Could it be expanded safely to arbitrary references,
2647 # without triggering too many false positives? The first
2648 # attempt triggered 5 warnings for mostly benign code in the regtest, hence
2649 # the restriction.
2650 # Here's the original regexp, for the reference:
2651 # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
2652 # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
2653 error(filename, linenum, 'runtime/member_string_references', 2,
2654 'const string& members are dangerous. It is much better to use '
2655 'alternatives, such as pointers or simple constants.')
2656
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002657 # Everything else in this function operates on class declarations.
2658 # Return early if the top of the nesting stack is not a class, or if
2659 # the class head is not completed yet.
2660 classinfo = nesting_state.InnermostClass()
2661 if not classinfo or not classinfo.seen_open_brace:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002662 return
2663
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002664 # The class may have been declared with namespace or classname qualifiers.
2665 # The constructor and destructor will not have those qualifiers.
2666 base_classname = classinfo.name.split('::')[-1]
2667
2668 # Look for single-argument constructors that aren't marked explicit.
avakulenko@google.com59146752014-08-11 20:20:55 +00002669 # Technically a valid construct, but against style. Also look for
2670 # non-single-argument constructors which are also technically valid, but
2671 # strongly suggest something is wrong.
2672 explicit_constructor_match = Match(
2673 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*'
2674 r'\(((?:[^()]|\([^()]*\))*)\)'
2675 % re.escape(base_classname),
2676 line)
2677
2678 if explicit_constructor_match:
2679 is_marked_explicit = explicit_constructor_match.group(1)
2680
2681 if not explicit_constructor_match.group(2):
2682 constructor_args = []
2683 else:
2684 constructor_args = explicit_constructor_match.group(2).split(',')
2685
2686 # collapse arguments so that commas in template parameter lists and function
2687 # argument parameter lists don't split arguments in two
2688 i = 0
2689 while i < len(constructor_args):
2690 constructor_arg = constructor_args[i]
2691 while (constructor_arg.count('<') > constructor_arg.count('>') or
2692 constructor_arg.count('(') > constructor_arg.count(')')):
2693 constructor_arg += ',' + constructor_args[i + 1]
2694 del constructor_args[i + 1]
2695 constructor_args[i] = constructor_arg
2696 i += 1
2697
2698 defaulted_args = [arg for arg in constructor_args if '=' in arg]
2699 noarg_constructor = (not constructor_args or # empty arg list
2700 # 'void' arg specifier
2701 (len(constructor_args) == 1 and
2702 constructor_args[0].strip() == 'void'))
2703 onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg
2704 not noarg_constructor) or
2705 # all but at most one arg defaulted
2706 (len(constructor_args) >= 1 and
2707 not noarg_constructor and
2708 len(defaulted_args) >= len(constructor_args) - 1))
2709 initializer_list_constructor = bool(
2710 onearg_constructor and
2711 Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
2712 copy_constructor = bool(
2713 onearg_constructor and
2714 Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
2715 % re.escape(base_classname), constructor_args[0].strip()))
2716
2717 if (not is_marked_explicit and
2718 onearg_constructor and
2719 not initializer_list_constructor and
2720 not copy_constructor):
2721 if defaulted_args:
2722 error(filename, linenum, 'runtime/explicit', 5,
2723 'Constructors callable with one argument '
2724 'should be marked explicit.')
2725 else:
2726 error(filename, linenum, 'runtime/explicit', 5,
2727 'Single-parameter constructors should be marked explicit.')
2728 elif is_marked_explicit and not onearg_constructor:
2729 if noarg_constructor:
2730 error(filename, linenum, 'runtime/explicit', 5,
2731 'Zero-parameter constructors should not be marked explicit.')
2732 else:
2733 error(filename, linenum, 'runtime/explicit', 0,
2734 'Constructors that require multiple arguments '
2735 'should not be marked explicit.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002736
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002737
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002738def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002739 """Checks for the correctness of various spacing around function calls.
2740
2741 Args:
2742 filename: The name of the current file.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002743 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002744 linenum: The number of the line to check.
2745 error: The function to call with any errors found.
2746 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002747 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002748
2749 # Since function calls often occur inside if/for/while/switch
2750 # expressions - which have their own, more liberal conventions - we
2751 # first see if we should be looking inside such an expression for a
2752 # function call, to which we can apply more strict standards.
2753 fncall = line # if there's no control flow construct, look at whole line
2754 for pattern in (r'\bif\s*\((.*)\)\s*{',
2755 r'\bfor\s*\((.*)\)\s*{',
2756 r'\bwhile\s*\((.*)\)\s*[{;]',
2757 r'\bswitch\s*\((.*)\)\s*{'):
2758 match = Search(pattern, line)
2759 if match:
2760 fncall = match.group(1) # look inside the parens for function calls
2761 break
2762
2763 # Except in if/for/while/switch, there should never be space
2764 # immediately inside parens (eg "f( 3, 4 )"). We make an exception
2765 # for nested parens ( (a+b) + c ). Likewise, there should never be
2766 # a space before a ( when it's a function argument. I assume it's a
2767 # function argument when the char before the whitespace is legal in
2768 # a function name (alnum + _) and we're not starting a macro. Also ignore
2769 # pointers and references to arrays and functions coz they're too tricky:
2770 # we use a very simple way to recognize these:
2771 # " (something)(maybe-something)" or
2772 # " (something)(maybe-something," or
2773 # " (something)[something]"
2774 # Note that we assume the contents of [] to be short enough that
2775 # they'll never need to wrap.
2776 if ( # Ignore control structures.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002777 not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2778 fncall) and
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002779 # Ignore pointers/references to functions.
2780 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
2781 # Ignore pointers/references to arrays.
2782 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
erg@google.com6317a9c2009-06-25 00:28:19 +00002783 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002784 error(filename, linenum, 'whitespace/parens', 4,
2785 'Extra space after ( in function call')
erg@google.com6317a9c2009-06-25 00:28:19 +00002786 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002787 error(filename, linenum, 'whitespace/parens', 2,
2788 'Extra space after (')
2789 if (Search(r'\w\s+\(', fncall) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002790 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002791 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
2792 not Search(r'\bcase\s+\(', fncall)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002793 # TODO(unknown): Space after an operator function seem to be a common
2794 # error, silence those for now by restricting them to highest verbosity.
2795 if Search(r'\boperator_*\b', line):
2796 error(filename, linenum, 'whitespace/parens', 0,
2797 'Extra space before ( in function call')
2798 else:
2799 error(filename, linenum, 'whitespace/parens', 4,
2800 'Extra space before ( in function call')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002801 # If the ) is followed only by a newline or a { + newline, assume it's
2802 # part of a control statement (if/while/etc), and don't complain
2803 if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002804 # If the closing parenthesis is preceded by only whitespaces,
2805 # try to give a more descriptive error message.
2806 if Search(r'^\s+\)', fncall):
2807 error(filename, linenum, 'whitespace/parens', 2,
2808 'Closing ) should be moved to the previous line')
2809 else:
2810 error(filename, linenum, 'whitespace/parens', 2,
2811 'Extra space before )')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002812
2813
2814def IsBlankLine(line):
2815 """Returns true if the given line is blank.
2816
2817 We consider a line to be blank if the line is empty or consists of
2818 only white spaces.
2819
2820 Args:
2821 line: A line of a string.
2822
2823 Returns:
2824 True, if the given line is blank.
2825 """
2826 return not line or line.isspace()
2827
2828
avakulenko@google.com59146752014-08-11 20:20:55 +00002829def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
2830 error):
2831 is_namespace_indent_item = (
2832 len(nesting_state.stack) > 1 and
2833 nesting_state.stack[-1].check_namespace_indentation and
2834 isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
2835 nesting_state.previous_stack_top == nesting_state.stack[-2])
2836
2837 if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
2838 clean_lines.elided, line):
2839 CheckItemIndentationInNamespace(filename, clean_lines.elided,
2840 line, error)
2841
2842
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002843def CheckForFunctionLengths(filename, clean_lines, linenum,
2844 function_state, error):
2845 """Reports for long function bodies.
2846
2847 For an overview why this is done, see:
2848 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
2849
2850 Uses a simplistic algorithm assuming other style guidelines
2851 (especially spacing) are followed.
2852 Only checks unindented functions, so class members are unchecked.
2853 Trivial bodies are unchecked, so constructors with huge initializer lists
2854 may be missed.
2855 Blank/comment lines are not counted so as to avoid encouraging the removal
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002856 of vertical space and comments just to get through a lint check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002857 NOLINT *on the last line of a function* disables this check.
2858
2859 Args:
2860 filename: The name of the current file.
2861 clean_lines: A CleansedLines instance containing the file.
2862 linenum: The number of the line to check.
2863 function_state: Current function name and lines in body so far.
2864 error: The function to call with any errors found.
2865 """
2866 lines = clean_lines.lines
2867 line = lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002868 joined_line = ''
2869
2870 starting_func = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002871 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002872 match_result = Match(regexp, line)
2873 if match_result:
2874 # If the name is all caps and underscores, figure it's a macro and
2875 # ignore it, unless it's TEST or TEST_F.
2876 function_name = match_result.group(1).split()[-1]
2877 if function_name == 'TEST' or function_name == 'TEST_F' or (
2878 not Match(r'[A-Z_]+$', function_name)):
2879 starting_func = True
2880
2881 if starting_func:
2882 body_found = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002883 for start_linenum in xrange(linenum, clean_lines.NumLines()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002884 start_line = lines[start_linenum]
2885 joined_line += ' ' + start_line.lstrip()
2886 if Search(r'(;|})', start_line): # Declarations and trivial functions
2887 body_found = True
2888 break # ... ignore
2889 elif Search(r'{', start_line):
2890 body_found = True
2891 function = Search(r'((\w|:)*)\(', line).group(1)
2892 if Match(r'TEST', function): # Handle TEST... macros
2893 parameter_regexp = Search(r'(\(.*\))', joined_line)
2894 if parameter_regexp: # Ignore bad syntax
2895 function += parameter_regexp.group(1)
2896 else:
2897 function += '()'
2898 function_state.Begin(function)
2899 break
2900 if not body_found:
erg@google.com6317a9c2009-06-25 00:28:19 +00002901 # No body for the function (or evidence of a non-function) was found.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002902 error(filename, linenum, 'readability/fn_size', 5,
2903 'Lint failed to find start of function body.')
2904 elif Match(r'^\}\s*$', line): # function end
erg@google.com35589e62010-11-17 18:58:16 +00002905 function_state.Check(error, filename, linenum)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002906 function_state.End()
2907 elif not Match(r'^\s*$', line):
2908 function_state.Count() # Count non-blank/non-comment lines.
2909
2910
2911_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2912
2913
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002914def CheckComment(line, filename, linenum, next_line_start, error):
2915 """Checks for common mistakes in comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002916
2917 Args:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002918 line: The line in question.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002919 filename: The name of the current file.
2920 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002921 next_line_start: The first non-whitespace column of the next line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002922 error: The function to call with any errors found.
2923 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002924 commentpos = line.find('//')
2925 if commentpos != -1:
2926 # Check if the // may be in quotes. If so, ignore it
2927 # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
2928 if (line.count('"', 0, commentpos) -
2929 line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes
2930 # Allow one space for new scopes, two spaces otherwise:
2931 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
2932 ((commentpos >= 1 and
2933 line[commentpos-1] not in string.whitespace) or
2934 (commentpos >= 2 and
2935 line[commentpos-2] not in string.whitespace))):
2936 error(filename, linenum, 'whitespace/comments', 2,
2937 'At least two spaces is best between code and comments')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002938
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002939 # Checks for common mistakes in TODO comments.
2940 comment = line[commentpos:]
2941 match = _RE_PATTERN_TODO.match(comment)
2942 if match:
2943 # One whitespace is correct; zero whitespace is handled elsewhere.
2944 leading_whitespace = match.group(1)
2945 if len(leading_whitespace) > 1:
2946 error(filename, linenum, 'whitespace/todo', 2,
2947 'Too many spaces before TODO')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002948
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002949 username = match.group(2)
2950 if not username:
2951 error(filename, linenum, 'readability/todo', 2,
2952 'Missing username in TODO; it should look like '
2953 '"// TODO(my_username): Stuff."')
2954
2955 middle_whitespace = match.group(3)
2956 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
2957 if middle_whitespace != ' ' and middle_whitespace != '':
2958 error(filename, linenum, 'whitespace/todo', 2,
2959 'TODO(my_username) should be followed by a space')
2960
2961 # If the comment contains an alphanumeric character, there
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002962 # should be a space somewhere between it and the // unless
2963 # it's a /// or //! Doxygen comment.
2964 if (Match(r'//[^ ]*\w', comment) and
2965 not Match(r'(///|//\!)(\s+|$)', comment)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002966 error(filename, linenum, 'whitespace/comments', 4,
2967 'Should have a space between // and comment')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002968
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002969
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002970def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
2971 """Checks for improper use of DISALLOW* macros.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002972
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002973 Args:
2974 filename: The name of the current file.
2975 clean_lines: A CleansedLines instance containing the file.
2976 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002977 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002978 the current stack of nested blocks being parsed.
2979 error: The function to call with any errors found.
2980 """
2981 line = clean_lines.elided[linenum] # get rid of comments and strings
2982
2983 matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002984 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
2985 if not matched:
2986 return
2987 if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo):
2988 if nesting_state.stack[-1].access != 'private':
2989 error(filename, linenum, 'readability/constructors', 3,
2990 '%s must be in the private: section' % matched.group(1))
2991
2992 else:
2993 # Found DISALLOW* macro outside a class declaration, or perhaps it
2994 # was used inside a function when it should have been part of the
2995 # class declaration. We could issue a warning here, but it
2996 # probably resulted in a compiler error already.
2997 pass
2998
2999
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003000def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003001 """Checks for the correctness of various spacing issues in the code.
3002
3003 Things we check for: spaces around operators, spaces after
3004 if/for/while/switch, no spaces around parens in function calls, two
3005 spaces between code and comment, don't start a block with a blank
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003006 line, don't end a function with a blank line, don't add a blank line
3007 after public/protected/private, don't have too many blank lines in a row.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003008
3009 Args:
3010 filename: The name of the current file.
3011 clean_lines: A CleansedLines instance containing the file.
3012 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003013 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003014 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003015 error: The function to call with any errors found.
3016 """
3017
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003018 # Don't use "elided" lines here, otherwise we can't check commented lines.
3019 # Don't want to use "raw" either, because we don't want to check inside C++11
3020 # raw strings,
3021 raw = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003022 line = raw[linenum]
3023
3024 # Before nixing comments, check if the line is blank for no good
3025 # reason. This includes the first line after a block is opened, and
3026 # blank lines at the end of a function (ie, right before a line like '}'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003027 #
3028 # Skip all the blank line checks if we are immediately inside a
3029 # namespace body. In other words, don't issue blank line warnings
3030 # for this block:
3031 # namespace {
3032 #
3033 # }
3034 #
3035 # A warning about missing end of namespace comments will be issued instead.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003036 #
3037 # Also skip blank line checks for 'extern "C"' blocks, which are formatted
3038 # like namespaces.
3039 if (IsBlankLine(line) and
3040 not nesting_state.InNamespaceBody() and
3041 not nesting_state.InExternC()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003042 elided = clean_lines.elided
3043 prev_line = elided[linenum - 1]
3044 prevbrace = prev_line.rfind('{')
3045 # TODO(unknown): Don't complain if line before blank line, and line after,
3046 # both start with alnums and are indented the same amount.
3047 # This ignores whitespace at the start of a namespace block
3048 # because those are not usually indented.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003049 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003050 # OK, we have a blank line at the start of a code block. Before we
3051 # complain, we check if it is an exception to the rule: The previous
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003052 # non-empty line has the parameters of a function header that are indented
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003053 # 4 spaces (because they did not fit in a 80 column line when placed on
3054 # the same line as the function name). We also check for the case where
3055 # the previous line is indented 6 spaces, which may happen when the
3056 # initializers of a constructor do not fit into a 80 column line.
3057 exception = False
3058 if Match(r' {6}\w', prev_line): # Initializer list?
3059 # We are looking for the opening column of initializer list, which
3060 # should be indented 4 spaces to cause 6 space indentation afterwards.
3061 search_position = linenum-2
3062 while (search_position >= 0
3063 and Match(r' {6}\w', elided[search_position])):
3064 search_position -= 1
3065 exception = (search_position >= 0
3066 and elided[search_position][:5] == ' :')
3067 else:
3068 # Search for the function arguments or an initializer list. We use a
3069 # simple heuristic here: If the line is indented 4 spaces; and we have a
3070 # closing paren, without the opening paren, followed by an opening brace
3071 # or colon (for initializer lists) we assume that it is the last line of
3072 # a function header. If we have a colon indented 4 spaces, it is an
3073 # initializer list.
3074 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3075 prev_line)
3076 or Match(r' {4}:', prev_line))
3077
3078 if not exception:
3079 error(filename, linenum, 'whitespace/blank_line', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003080 'Redundant blank line at the start of a code block '
3081 'should be deleted.')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003082 # Ignore blank lines at the end of a block in a long if-else
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003083 # chain, like this:
3084 # if (condition1) {
3085 # // Something followed by a blank line
3086 #
3087 # } else if (condition2) {
3088 # // Something else
3089 # }
3090 if linenum + 1 < clean_lines.NumLines():
3091 next_line = raw[linenum + 1]
3092 if (next_line
3093 and Match(r'\s*}', next_line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003094 and next_line.find('} else ') == -1):
3095 error(filename, linenum, 'whitespace/blank_line', 3,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003096 'Redundant blank line at the end of a code block '
3097 'should be deleted.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003098
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003099 matched = Match(r'\s*(public|protected|private):', prev_line)
3100 if matched:
3101 error(filename, linenum, 'whitespace/blank_line', 3,
3102 'Do not leave a blank line after "%s:"' % matched.group(1))
3103
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003104 # Next, check comments
3105 next_line_start = 0
3106 if linenum + 1 < clean_lines.NumLines():
3107 next_line = raw[linenum + 1]
3108 next_line_start = len(next_line) - len(next_line.lstrip())
3109 CheckComment(line, filename, linenum, next_line_start, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003110
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003111 # get rid of comments and strings
3112 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003113
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003114 # You shouldn't have spaces before your brackets, except maybe after
3115 # 'delete []' or 'return []() {};'
3116 if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
3117 error(filename, linenum, 'whitespace/braces', 5,
3118 'Extra space before [')
3119
3120 # In range-based for, we wanted spaces before and after the colon, but
3121 # not around "::" tokens that might appear.
3122 if (Search(r'for *\(.*[^:]:[^: ]', line) or
3123 Search(r'for *\(.*[^: ]:[^:]', line)):
3124 error(filename, linenum, 'whitespace/forcolon', 2,
3125 'Missing space around colon in range-based for loop')
3126
3127
3128def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3129 """Checks for horizontal spacing around operators.
3130
3131 Args:
3132 filename: The name of the current file.
3133 clean_lines: A CleansedLines instance containing the file.
3134 linenum: The number of the line to check.
3135 error: The function to call with any errors found.
3136 """
3137 line = clean_lines.elided[linenum]
3138
3139 # Don't try to do spacing checks for operator methods. Do this by
3140 # replacing the troublesome characters with something else,
3141 # preserving column position for all other characters.
3142 #
3143 # The replacement is done repeatedly to avoid false positives from
3144 # operators that call operators.
3145 while True:
3146 match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3147 if match:
3148 line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
3149 else:
3150 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003151
3152 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
3153 # Otherwise not. Note we only check for non-spaces on *both* sides;
3154 # sometimes people put non-spaces on one side when aligning ='s among
3155 # many lines (not that this is behavior that I approve of...)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003156 if ((Search(r'[\w.]=', line) or
3157 Search(r'=[\w.]', line))
3158 and not Search(r'\b(if|while|for) ', line)
3159 # Operators taken from [lex.operators] in C++11 standard.
3160 and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3161 and not Search(r'operator=', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003162 error(filename, linenum, 'whitespace/operators', 4,
3163 'Missing spaces around =')
3164
3165 # It's ok not to have spaces around binary operators like + - * /, but if
3166 # there's too little whitespace, we get concerned. It's hard to tell,
3167 # though, so we punt on this one for now. TODO.
3168
3169 # You should always have whitespace around binary operators.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003170 #
3171 # Check <= and >= first to avoid false positives with < and >, then
3172 # check non-include lines for spacing around < and >.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003173 #
3174 # If the operator is followed by a comma, assume it's be used in a
3175 # macro context and don't do any checks. This avoids false
3176 # positives.
3177 #
3178 # Note that && is not included here. Those are checked separately
3179 # in CheckRValueReference
3180 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003181 if match:
3182 error(filename, linenum, 'whitespace/operators', 3,
3183 'Missing spaces around %s' % match.group(1))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003184 elif not Match(r'#.*include', line):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003185 # Look for < that is not surrounded by spaces. This is only
3186 # triggered if both sides are missing spaces, even though
3187 # technically should should flag if at least one side is missing a
3188 # space. This is done to avoid some false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003189 match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
3190 if match:
3191 (_, _, end_pos) = CloseExpression(
3192 clean_lines, linenum, len(match.group(1)))
3193 if end_pos <= -1:
3194 error(filename, linenum, 'whitespace/operators', 3,
3195 'Missing spaces around <')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003196
3197 # Look for > that is not surrounded by spaces. Similar to the
3198 # above, we only trigger if both sides are missing spaces to avoid
3199 # false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003200 match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
3201 if match:
3202 (_, _, start_pos) = ReverseCloseExpression(
3203 clean_lines, linenum, len(match.group(1)))
3204 if start_pos <= -1:
3205 error(filename, linenum, 'whitespace/operators', 3,
3206 'Missing spaces around >')
3207
3208 # We allow no-spaces around << when used like this: 10<<20, but
3209 # not otherwise (particularly, not when used as streams)
avakulenko@google.com59146752014-08-11 20:20:55 +00003210 #
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003211 # We also allow operators following an opening parenthesis, since
3212 # those tend to be macros that deal with operators.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003213 match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line)
3214 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003215 not (match.group(1) == 'operator' and match.group(2) == ';')):
3216 error(filename, linenum, 'whitespace/operators', 3,
3217 'Missing spaces around <<')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003218
3219 # We allow no-spaces around >> for almost anything. This is because
3220 # C++11 allows ">>" to close nested templates, which accounts for
3221 # most cases when ">>" is not followed by a space.
3222 #
3223 # We still warn on ">>" followed by alpha character, because that is
3224 # likely due to ">>" being used for right shifts, e.g.:
3225 # value >> alpha
3226 #
3227 # When ">>" is used to close templates, the alphanumeric letter that
3228 # follows would be part of an identifier, and there should still be
3229 # a space separating the template type and the identifier.
3230 # type<type<type>> alpha
3231 match = Search(r'>>[a-zA-Z_]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003232 if match:
3233 error(filename, linenum, 'whitespace/operators', 3,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003234 'Missing spaces around >>')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003235
3236 # There shouldn't be space around unary operators
3237 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3238 if match:
3239 error(filename, linenum, 'whitespace/operators', 4,
3240 'Extra space for operator %s' % match.group(1))
3241
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003242
3243def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
3244 """Checks for horizontal spacing around parentheses.
3245
3246 Args:
3247 filename: The name of the current file.
3248 clean_lines: A CleansedLines instance containing the file.
3249 linenum: The number of the line to check.
3250 error: The function to call with any errors found.
3251 """
3252 line = clean_lines.elided[linenum]
3253
3254 # No spaces after an if, while, switch, or for
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003255 match = Search(r' (if\(|for\(|while\(|switch\()', line)
3256 if match:
3257 error(filename, linenum, 'whitespace/parens', 5,
3258 'Missing space before ( in %s' % match.group(1))
3259
3260 # For if/for/while/switch, the left and right parens should be
3261 # consistent about how many spaces are inside the parens, and
3262 # there should either be zero or one spaces inside the parens.
3263 # We don't want: "if ( foo)" or "if ( foo )".
erg@google.com6317a9c2009-06-25 00:28:19 +00003264 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003265 match = Search(r'\b(if|for|while|switch)\s*'
3266 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3267 line)
3268 if match:
3269 if len(match.group(2)) != len(match.group(4)):
3270 if not (match.group(3) == ';' and
erg@google.com6317a9c2009-06-25 00:28:19 +00003271 len(match.group(2)) == 1 + len(match.group(4)) or
3272 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003273 error(filename, linenum, 'whitespace/parens', 5,
3274 'Mismatching spaces inside () in %s' % match.group(1))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003275 if len(match.group(2)) not in [0, 1]:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003276 error(filename, linenum, 'whitespace/parens', 5,
3277 'Should have zero or one spaces inside ( and ) in %s' %
3278 match.group(1))
3279
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003280
3281def CheckCommaSpacing(filename, clean_lines, linenum, error):
3282 """Checks for horizontal spacing near commas and semicolons.
3283
3284 Args:
3285 filename: The name of the current file.
3286 clean_lines: A CleansedLines instance containing the file.
3287 linenum: The number of the line to check.
3288 error: The function to call with any errors found.
3289 """
3290 raw = clean_lines.lines_without_raw_strings
3291 line = clean_lines.elided[linenum]
3292
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003293 # You should always have a space after a comma (either as fn arg or operator)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003294 #
3295 # This does not apply when the non-space character following the
3296 # comma is another comma, since the only time when that happens is
3297 # for empty macro arguments.
3298 #
3299 # We run this check in two passes: first pass on elided lines to
3300 # verify that lines contain missing whitespaces, second pass on raw
3301 # lines to confirm that those missing whitespaces are not due to
3302 # elided comments.
avakulenko@google.com59146752014-08-11 20:20:55 +00003303 if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
3304 Search(r',[^,\s]', raw[linenum])):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003305 error(filename, linenum, 'whitespace/comma', 3,
3306 'Missing space after ,')
3307
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003308 # You should always have a space after a semicolon
3309 # except for few corner cases
3310 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
3311 # space after ;
3312 if Search(r';[^\s};\\)/]', line):
3313 error(filename, linenum, 'whitespace/semicolon', 3,
3314 'Missing space after ;')
3315
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003316
3317def CheckBracesSpacing(filename, clean_lines, linenum, error):
3318 """Checks for horizontal spacing near commas.
3319
3320 Args:
3321 filename: The name of the current file.
3322 clean_lines: A CleansedLines instance containing the file.
3323 linenum: The number of the line to check.
3324 error: The function to call with any errors found.
3325 """
3326 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003327
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003328 # Except after an opening paren, or after another opening brace (in case of
3329 # an initializer list, for instance), you should have spaces before your
3330 # braces. And since you should never have braces at the beginning of a line,
3331 # this is an easy test.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003332 match = Match(r'^(.*[^ ({>]){', line)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003333 if match:
3334 # Try a bit harder to check for brace initialization. This
3335 # happens in one of the following forms:
3336 # Constructor() : initializer_list_{} { ... }
3337 # Constructor{}.MemberFunction()
3338 # Type variable{};
3339 # FunctionCall(type{}, ...);
3340 # LastArgument(..., type{});
3341 # LOG(INFO) << type{} << " ...";
3342 # map_of_type[{...}] = ...;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003343 # ternary = expr ? new type{} : nullptr;
3344 # OuterTemplate<InnerTemplateConstructor<Type>{}>
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003345 #
3346 # We check for the character following the closing brace, and
3347 # silence the warning if it's one of those listed above, i.e.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003348 # "{.;,)<>]:".
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003349 #
3350 # To account for nested initializer list, we allow any number of
3351 # closing braces up to "{;,)<". We can't simply silence the
3352 # warning on first sight of closing brace, because that would
3353 # cause false negatives for things that are not initializer lists.
3354 # Silence this: But not this:
3355 # Outer{ if (...) {
3356 # Inner{...} if (...){ // Missing space before {
3357 # }; }
3358 #
3359 # There is a false negative with this approach if people inserted
3360 # spurious semicolons, e.g. "if (cond){};", but we will catch the
3361 # spurious semicolon with a separate check.
3362 (endline, endlinenum, endpos) = CloseExpression(
3363 clean_lines, linenum, len(match.group(1)))
3364 trailing_text = ''
3365 if endpos > -1:
3366 trailing_text = endline[endpos:]
3367 for offset in xrange(endlinenum + 1,
3368 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3369 trailing_text += clean_lines.elided[offset]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003370 if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003371 error(filename, linenum, 'whitespace/braces', 5,
3372 'Missing space before {')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003373
3374 # Make sure '} else {' has spaces.
3375 if Search(r'}else', line):
3376 error(filename, linenum, 'whitespace/braces', 5,
3377 'Missing space before else')
3378
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003379 # You shouldn't have a space before a semicolon at the end of the line.
3380 # There's a special case for "for" since the style guide allows space before
3381 # the semicolon there.
3382 if Search(r':\s*;\s*$', line):
3383 error(filename, linenum, 'whitespace/semicolon', 5,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003384 'Semicolon defining empty statement. Use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003385 elif Search(r'^\s*;\s*$', line):
3386 error(filename, linenum, 'whitespace/semicolon', 5,
3387 'Line contains only semicolon. If this should be an empty statement, '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003388 'use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003389 elif (Search(r'\s+;\s*$', line) and
3390 not Search(r'\bfor\b', line)):
3391 error(filename, linenum, 'whitespace/semicolon', 5,
3392 'Extra space before last semicolon. If this should be an empty '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003393 'statement, use {} instead.')
3394
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003395
3396def IsDecltype(clean_lines, linenum, column):
3397 """Check if the token ending on (linenum, column) is decltype().
3398
3399 Args:
3400 clean_lines: A CleansedLines instance containing the file.
3401 linenum: the number of the line to check.
3402 column: end column of the token to check.
3403 Returns:
3404 True if this token is decltype() expression, False otherwise.
3405 """
3406 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
3407 if start_col < 0:
3408 return False
3409 if Search(r'\bdecltype\s*$', text[0:start_col]):
3410 return True
3411 return False
3412
3413
3414def IsTemplateParameterList(clean_lines, linenum, column):
3415 """Check if the token ending on (linenum, column) is the end of template<>.
3416
3417 Args:
3418 clean_lines: A CleansedLines instance containing the file.
3419 linenum: the number of the line to check.
3420 column: end column of the token to check.
3421 Returns:
3422 True if this token is end of a template parameter list, False otherwise.
3423 """
3424 (_, startline, startpos) = ReverseCloseExpression(
3425 clean_lines, linenum, column)
3426 if (startpos > -1 and
3427 Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
3428 return True
3429 return False
3430
3431
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003432def IsRValueType(typenames, clean_lines, nesting_state, linenum, column):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003433 """Check if the token ending on (linenum, column) is a type.
3434
3435 Assumes that text to the right of the column is "&&" or a function
3436 name.
3437
3438 Args:
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003439 typenames: set of type names from template-argument-list.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003440 clean_lines: A CleansedLines instance containing the file.
3441 nesting_state: A NestingState instance which maintains information about
3442 the current stack of nested blocks being parsed.
3443 linenum: the number of the line to check.
3444 column: end column of the token to check.
3445 Returns:
3446 True if this token is a type, False if we are not sure.
3447 """
3448 prefix = clean_lines.elided[linenum][0:column]
3449
3450 # Get one word to the left. If we failed to do so, this is most
3451 # likely not a type, since it's unlikely that the type name and "&&"
3452 # would be split across multiple lines.
3453 match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
3454 if not match:
3455 return False
3456
3457 # Check text following the token. If it's "&&>" or "&&," or "&&...", it's
3458 # most likely a rvalue reference used inside a template.
3459 suffix = clean_lines.elided[linenum][column:]
3460 if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
3461 return True
3462
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003463 # Check for known types and end of templates:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003464 # int&& variable
3465 # vector<int>&& variable
3466 #
3467 # Because this function is called recursively, we also need to
3468 # recognize pointer and reference types:
3469 # int* Function()
3470 # int& Function()
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003471 if (match.group(2) in typenames or
3472 match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
3473 'short', 'int', 'long', 'signed', 'unsigned',
3474 'float', 'double', 'void', 'auto', '>', '*', '&']):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003475 return True
3476
3477 # If we see a close parenthesis, look for decltype on the other side.
3478 # decltype would unambiguously identify a type, anything else is
3479 # probably a parenthesized expression and not a type.
3480 if match.group(2) == ')':
3481 return IsDecltype(
3482 clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
3483
3484 # Check for casts and cv-qualifiers.
3485 # match.group(1) remainder
3486 # -------------- ---------
3487 # const_cast< type&&
3488 # const type&&
3489 # type const&&
3490 if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
3491 r'reinterpret_cast\s*<|\w+\s)\s*$',
3492 match.group(1)):
3493 return True
3494
3495 # Look for a preceding symbol that might help differentiate the context.
3496 # These are the cases that would be ambiguous:
3497 # match.group(1) remainder
3498 # -------------- ---------
3499 # Call ( expression &&
3500 # Declaration ( type&&
3501 # sizeof ( type&&
3502 # if ( expression &&
3503 # while ( expression &&
3504 # for ( type&&
3505 # for( ; expression &&
3506 # statement ; type&&
3507 # block { type&&
3508 # constructor { expression &&
3509 start = linenum
3510 line = match.group(1)
3511 match_symbol = None
3512 while start >= 0:
3513 # We want to skip over identifiers and commas to get to a symbol.
3514 # Commas are skipped so that we can find the opening parenthesis
3515 # for function parameter lists.
3516 match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
3517 if match_symbol:
3518 break
3519 start -= 1
3520 line = clean_lines.elided[start]
3521
3522 if not match_symbol:
3523 # Probably the first statement in the file is an rvalue reference
3524 return True
3525
3526 if match_symbol.group(2) == '}':
3527 # Found closing brace, probably an indicate of this:
3528 # block{} type&&
3529 return True
3530
3531 if match_symbol.group(2) == ';':
3532 # Found semicolon, probably one of these:
3533 # for(; expression &&
3534 # statement; type&&
3535
3536 # Look for the previous 'for(' in the previous lines.
3537 before_text = match_symbol.group(1)
3538 for i in xrange(start - 1, max(start - 6, 0), -1):
3539 before_text = clean_lines.elided[i] + before_text
3540 if Search(r'for\s*\([^{};]*$', before_text):
3541 # This is the condition inside a for-loop
3542 return False
3543
3544 # Did not find a for-init-statement before this semicolon, so this
3545 # is probably a new statement and not a condition.
3546 return True
3547
3548 if match_symbol.group(2) == '{':
3549 # Found opening brace, probably one of these:
3550 # block{ type&& = ... ; }
3551 # constructor{ expression && expression }
3552
3553 # Look for a closing brace or a semicolon. If we see a semicolon
3554 # first, this is probably a rvalue reference.
3555 line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
3556 end = start
3557 depth = 1
3558 while True:
3559 for ch in line:
3560 if ch == ';':
3561 return True
3562 elif ch == '{':
3563 depth += 1
3564 elif ch == '}':
3565 depth -= 1
3566 if depth == 0:
3567 return False
3568 end += 1
3569 if end >= clean_lines.NumLines():
3570 break
3571 line = clean_lines.elided[end]
3572 # Incomplete program?
3573 return False
3574
3575 if match_symbol.group(2) == '(':
3576 # Opening parenthesis. Need to check what's to the left of the
3577 # parenthesis. Look back one extra line for additional context.
3578 before_text = match_symbol.group(1)
3579 if linenum > 1:
3580 before_text = clean_lines.elided[linenum - 1] + before_text
3581 before_text = match_symbol.group(1)
3582
3583 # Patterns that are likely to be types:
3584 # [](type&&
3585 # for (type&&
3586 # sizeof(type&&
3587 # operator=(type&&
3588 #
3589 if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
3590 return True
3591
3592 # Patterns that are likely to be expressions:
3593 # if (expression &&
3594 # while (expression &&
3595 # : initializer(expression &&
3596 # , initializer(expression &&
3597 # ( FunctionCall(expression &&
3598 # + FunctionCall(expression &&
3599 # + (expression &&
3600 #
3601 # The last '+' represents operators such as '+' and '-'.
3602 if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
3603 return False
3604
3605 # Something else. Check that tokens to the left look like
3606 # return_type function_name
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003607 match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003608 match_symbol.group(1))
3609 if match_func:
3610 # Check for constructors, which don't have return types.
avakulenko@google.com59146752014-08-11 20:20:55 +00003611 if Search(r'\b(?:explicit|inline)$', match_func.group(1)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003612 return True
3613 implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
3614 if (implicit_constructor and
3615 implicit_constructor.group(1) == implicit_constructor.group(2)):
3616 return True
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003617 return IsRValueType(typenames, clean_lines, nesting_state, linenum,
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003618 len(match_func.group(1)))
3619
3620 # Nothing before the function name. If this is inside a block scope,
3621 # this is probably a function call.
3622 return not (nesting_state.previous_stack_top and
3623 nesting_state.previous_stack_top.IsBlockInfo())
3624
3625 if match_symbol.group(2) == '>':
3626 # Possibly a closing bracket, check that what's on the other side
3627 # looks like the start of a template.
3628 return IsTemplateParameterList(
3629 clean_lines, start, len(match_symbol.group(1)))
3630
3631 # Some other symbol, usually something like "a=b&&c". This is most
3632 # likely not a type.
3633 return False
3634
3635
avakulenko@google.com59146752014-08-11 20:20:55 +00003636def IsDeletedOrDefault(clean_lines, linenum):
3637 """Check if current constructor or operator is deleted or default.
3638
3639 Args:
3640 clean_lines: A CleansedLines instance containing the file.
3641 linenum: The number of the line to check.
3642 Returns:
3643 True if this is a deleted or default constructor.
3644 """
3645 open_paren = clean_lines.elided[linenum].find('(')
3646 if open_paren < 0:
3647 return False
3648 (close_line, _, close_paren) = CloseExpression(
3649 clean_lines, linenum, open_paren)
3650 if close_paren < 0:
3651 return False
3652 return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:])
3653
3654
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003655def IsRValueAllowed(clean_lines, linenum, typenames):
avakulenko@google.com59146752014-08-11 20:20:55 +00003656 """Check if RValue reference is allowed on a particular line.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003657
3658 Args:
3659 clean_lines: A CleansedLines instance containing the file.
3660 linenum: The number of the line to check.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003661 typenames: set of type names from template-argument-list.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003662 Returns:
3663 True if line is within the region where RValue references are allowed.
3664 """
avakulenko@google.com59146752014-08-11 20:20:55 +00003665 # Allow region marked by PUSH/POP macros
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003666 for i in xrange(linenum, 0, -1):
3667 line = clean_lines.elided[i]
3668 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3669 if not line.endswith('PUSH'):
3670 return False
3671 for j in xrange(linenum, clean_lines.NumLines(), 1):
3672 line = clean_lines.elided[j]
3673 if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3674 return line.endswith('POP')
avakulenko@google.com59146752014-08-11 20:20:55 +00003675
3676 # Allow operator=
3677 line = clean_lines.elided[linenum]
3678 if Search(r'\boperator\s*=\s*\(', line):
3679 return IsDeletedOrDefault(clean_lines, linenum)
3680
3681 # Allow constructors
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003682 match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line)
avakulenko@google.com59146752014-08-11 20:20:55 +00003683 if match and match.group(1) == match.group(2):
3684 return IsDeletedOrDefault(clean_lines, linenum)
3685 if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line):
3686 return IsDeletedOrDefault(clean_lines, linenum)
3687
3688 if Match(r'\s*[\w<>]+\s*\(', line):
3689 previous_line = 'ReturnType'
3690 if linenum > 0:
3691 previous_line = clean_lines.elided[linenum - 1]
3692 if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line):
3693 return IsDeletedOrDefault(clean_lines, linenum)
3694
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003695 # Reject types not mentioned in template-argument-list
3696 while line:
3697 match = Match(r'^.*?(\w+)\s*&&(.*)$', line)
3698 if not match:
3699 break
3700 if match.group(1) not in typenames:
3701 return False
3702 line = match.group(2)
3703
3704 # All RValue types that were in template-argument-list should have
3705 # been removed by now. Those were allowed, assuming that they will
3706 # be forwarded.
3707 #
3708 # If there are no remaining RValue types left (i.e. types that were
3709 # not found in template-argument-list), flag those as not allowed.
3710 return line.find('&&') < 0
3711
3712
3713def GetTemplateArgs(clean_lines, linenum):
3714 """Find list of template arguments associated with this function declaration.
3715
3716 Args:
3717 clean_lines: A CleansedLines instance containing the file.
3718 linenum: Line number containing the start of the function declaration,
3719 usually one line after the end of the template-argument-list.
3720 Returns:
3721 Set of type names, or empty set if this does not appear to have
3722 any template parameters.
3723 """
3724 # Find start of function
3725 func_line = linenum
3726 while func_line > 0:
3727 line = clean_lines.elided[func_line]
3728 if Match(r'^\s*$', line):
3729 return set()
3730 if line.find('(') >= 0:
3731 break
3732 func_line -= 1
3733 if func_line == 0:
3734 return set()
3735
3736 # Collapse template-argument-list into a single string
3737 argument_list = ''
3738 match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line])
3739 if match:
3740 # template-argument-list on the same line as function name
3741 start_col = len(match.group(1))
3742 _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col)
3743 if end_col > -1 and end_line == func_line:
3744 start_col += 1 # Skip the opening bracket
3745 argument_list = clean_lines.elided[func_line][start_col:end_col]
3746
3747 elif func_line > 1:
3748 # template-argument-list one line before function name
3749 match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1])
3750 if match:
3751 end_col = len(match.group(1))
3752 _, start_line, start_col = ReverseCloseExpression(
3753 clean_lines, func_line - 1, end_col)
3754 if start_col > -1:
3755 start_col += 1 # Skip the opening bracket
3756 while start_line < func_line - 1:
3757 argument_list += clean_lines.elided[start_line][start_col:]
3758 start_col = 0
3759 start_line += 1
3760 argument_list += clean_lines.elided[func_line - 1][start_col:end_col]
3761
3762 if not argument_list:
3763 return set()
3764
3765 # Extract type names
3766 typenames = set()
3767 while True:
3768 match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$',
3769 argument_list)
3770 if not match:
3771 break
3772 typenames.add(match.group(1))
3773 argument_list = match.group(2)
3774 return typenames
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003775
3776
3777def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error):
3778 """Check for rvalue references.
3779
3780 Args:
3781 filename: The name of the current file.
3782 clean_lines: A CleansedLines instance containing the file.
3783 linenum: The number of the line to check.
3784 nesting_state: A NestingState instance which maintains information about
3785 the current stack of nested blocks being parsed.
3786 error: The function to call with any errors found.
3787 """
3788 # Find lines missing spaces around &&.
3789 # TODO(unknown): currently we don't check for rvalue references
3790 # with spaces surrounding the && to avoid false positives with
3791 # boolean expressions.
3792 line = clean_lines.elided[linenum]
3793 match = Match(r'^(.*\S)&&', line)
3794 if not match:
3795 match = Match(r'(.*)&&\S', line)
3796 if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)):
3797 return
3798
3799 # Either poorly formed && or an rvalue reference, check the context
3800 # to get a more accurate error message. Mostly we want to determine
3801 # if what's to the left of "&&" is a type or not.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003802 typenames = GetTemplateArgs(clean_lines, linenum)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003803 and_pos = len(match.group(1))
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003804 if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos):
3805 if not IsRValueAllowed(clean_lines, linenum, typenames):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003806 error(filename, linenum, 'build/c++11', 3,
3807 'RValue references are an unapproved C++ feature.')
3808 else:
3809 error(filename, linenum, 'whitespace/operators', 3,
3810 'Missing spaces around &&')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003811
3812
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003813def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
3814 """Checks for additional blank line issues related to sections.
3815
3816 Currently the only thing checked here is blank line before protected/private.
3817
3818 Args:
3819 filename: The name of the current file.
3820 clean_lines: A CleansedLines instance containing the file.
3821 class_info: A _ClassInfo objects.
3822 linenum: The number of the line to check.
3823 error: The function to call with any errors found.
3824 """
3825 # Skip checks if the class is small, where small means 25 lines or less.
3826 # 25 lines seems like a good cutoff since that's the usual height of
3827 # terminals, and any class that can't fit in one screen can't really
3828 # be considered "small".
3829 #
3830 # Also skip checks if we are on the first line. This accounts for
3831 # classes that look like
3832 # class Foo { public: ... };
3833 #
3834 # If we didn't find the end of the class, last_line would be zero,
3835 # and the check will be skipped by the first condition.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003836 if (class_info.last_line - class_info.starting_linenum <= 24 or
3837 linenum <= class_info.starting_linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003838 return
3839
3840 matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
3841 if matched:
3842 # Issue warning if the line before public/protected/private was
3843 # not a blank line, but don't do this if the previous line contains
3844 # "class" or "struct". This can happen two ways:
3845 # - We are at the beginning of the class.
3846 # - We are forward-declaring an inner class that is semantically
3847 # private, but needed to be public for implementation reasons.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003848 # Also ignores cases where the previous line ends with a backslash as can be
3849 # common when defining classes in C macros.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003850 prev_line = clean_lines.lines[linenum - 1]
3851 if (not IsBlankLine(prev_line) and
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003852 not Search(r'\b(class|struct)\b', prev_line) and
3853 not Search(r'\\$', prev_line)):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003854 # Try a bit harder to find the beginning of the class. This is to
3855 # account for multi-line base-specifier lists, e.g.:
3856 # class Derived
3857 # : public Base {
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003858 end_class_head = class_info.starting_linenum
3859 for i in range(class_info.starting_linenum, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003860 if Search(r'\{\s*$', clean_lines.lines[i]):
3861 end_class_head = i
3862 break
3863 if end_class_head < linenum - 1:
3864 error(filename, linenum, 'whitespace/blank_line', 3,
3865 '"%s:" should be preceded by a blank line' % matched.group(1))
3866
3867
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003868def GetPreviousNonBlankLine(clean_lines, linenum):
3869 """Return the most recent non-blank line and its line number.
3870
3871 Args:
3872 clean_lines: A CleansedLines instance containing the file contents.
3873 linenum: The number of the line to check.
3874
3875 Returns:
3876 A tuple with two elements. The first element is the contents of the last
3877 non-blank line before the current line, or the empty string if this is the
3878 first non-blank line. The second is the line number of that line, or -1
3879 if this is the first non-blank line.
3880 """
3881
3882 prevlinenum = linenum - 1
3883 while prevlinenum >= 0:
3884 prevline = clean_lines.elided[prevlinenum]
3885 if not IsBlankLine(prevline): # if not a blank line...
3886 return (prevline, prevlinenum)
3887 prevlinenum -= 1
3888 return ('', -1)
3889
3890
3891def CheckBraces(filename, clean_lines, linenum, error):
3892 """Looks for misplaced braces (e.g. at the end of line).
3893
3894 Args:
3895 filename: The name of the current file.
3896 clean_lines: A CleansedLines instance containing the file.
3897 linenum: The number of the line to check.
3898 error: The function to call with any errors found.
3899 """
3900
3901 line = clean_lines.elided[linenum] # get rid of comments and strings
3902
3903 if Match(r'\s*{\s*$', line):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003904 # We allow an open brace to start a line in the case where someone is using
3905 # braces in a block to explicitly create a new scope, which is commonly used
3906 # to control the lifetime of stack-allocated variables. Braces are also
3907 # used for brace initializers inside function calls. We don't detect this
3908 # perfectly: we just don't complain if the last non-whitespace character on
3909 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
3910 # previous line starts a preprocessor block.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003911 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003912 if (not Search(r'[,;:}{(]\s*$', prevline) and
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003913 not Match(r'\s*#', prevline)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003914 error(filename, linenum, 'whitespace/braces', 4,
3915 '{ should almost always be at the end of the previous line')
3916
3917 # An else clause should be on the same line as the preceding closing brace.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003918 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003919 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3920 if Match(r'\s*}\s*$', prevline):
3921 error(filename, linenum, 'whitespace/newline', 4,
3922 'An else should appear on the same line as the preceding }')
3923
3924 # If braces come on one side of an else, they should be on both.
3925 # However, we have to worry about "else if" that spans multiple lines!
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003926 if Search(r'else if\s*\(', line): # could be multi-line if
3927 brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
3928 # find the ( after the if
3929 pos = line.find('else if')
3930 pos = line.find('(', pos)
3931 if pos > 0:
3932 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
3933 brace_on_right = endline[endpos:].find('{') != -1
3934 if brace_on_left != brace_on_right: # must be brace after if
3935 error(filename, linenum, 'readability/braces', 5,
3936 'If an else has a brace on one side, it should have it on both')
3937 elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
3938 error(filename, linenum, 'readability/braces', 5,
3939 'If an else has a brace on one side, it should have it on both')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003940
3941 # Likewise, an else should never have the else clause on the same line
3942 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
3943 error(filename, linenum, 'whitespace/newline', 4,
3944 'Else clause should never be on same line as else (use 2 lines)')
3945
3946 # In the same way, a do/while should never be on one line
3947 if Match(r'\s*do [^\s{]', line):
3948 error(filename, linenum, 'whitespace/newline', 4,
3949 'do/while clauses should not be on a single line')
3950
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003951 # Check single-line if/else bodies. The style guide says 'curly braces are not
3952 # required for single-line statements'. We additionally allow multi-line,
3953 # single statements, but we reject anything with more than one semicolon in
3954 # it. This means that the first semicolon after the if should be at the end of
3955 # its line, and the line after that should have an indent level equal to or
3956 # lower than the if. We also check for ambiguous if/else nesting without
3957 # braces.
3958 if_else_match = Search(r'\b(if\s*\(|else\b)', line)
3959 if if_else_match and not Match(r'\s*#', line):
3960 if_indent = GetIndentLevel(line)
3961 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3962 if_match = Search(r'\bif\s*\(', line)
3963 if if_match:
3964 # This could be a multiline if condition, so find the end first.
3965 pos = if_match.end() - 1
3966 (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
3967 # Check for an opening brace, either directly after the if or on the next
3968 # line. If found, this isn't a single-statement conditional.
3969 if (not Match(r'\s*{', endline[endpos:])
3970 and not (Match(r'\s*$', endline[endpos:])
3971 and endlinenum < (len(clean_lines.elided) - 1)
3972 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
3973 while (endlinenum < len(clean_lines.elided)
3974 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3975 endlinenum += 1
3976 endpos = 0
3977 if endlinenum < len(clean_lines.elided):
3978 endline = clean_lines.elided[endlinenum]
3979 # We allow a mix of whitespace and closing braces (e.g. for one-liner
3980 # methods) and a single \ after the semicolon (for macros)
3981 endpos = endline.find(';')
3982 if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
avakulenko@google.com59146752014-08-11 20:20:55 +00003983 # Semicolon isn't the last character, there's something trailing.
3984 # Output a warning if the semicolon is not contained inside
3985 # a lambda expression.
3986 if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3987 endline):
3988 error(filename, linenum, 'readability/braces', 4,
3989 'If/else bodies with multiple statements require braces')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003990 elif endlinenum < len(clean_lines.elided) - 1:
3991 # Make sure the next line is dedented
3992 next_line = clean_lines.elided[endlinenum + 1]
3993 next_indent = GetIndentLevel(next_line)
3994 # With ambiguous nested if statements, this will error out on the
3995 # if that *doesn't* match the else, regardless of whether it's the
3996 # inner one or outer one.
3997 if (if_match and Match(r'\s*else\b', next_line)
3998 and next_indent != if_indent):
3999 error(filename, linenum, 'readability/braces', 4,
4000 'Else clause should be indented at the same level as if. '
4001 'Ambiguous nested if/else chains require braces.')
4002 elif next_indent > if_indent:
4003 error(filename, linenum, 'readability/braces', 4,
4004 'If/else bodies with multiple statements require braces')
4005
4006
4007def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
4008 """Looks for redundant trailing semicolon.
4009
4010 Args:
4011 filename: The name of the current file.
4012 clean_lines: A CleansedLines instance containing the file.
4013 linenum: The number of the line to check.
4014 error: The function to call with any errors found.
4015 """
4016
4017 line = clean_lines.elided[linenum]
4018
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004019 # Block bodies should not be followed by a semicolon. Due to C++11
4020 # brace initialization, there are more places where semicolons are
4021 # required than not, so we use a whitelist approach to check these
4022 # rather than a blacklist. These are the places where "};" should
4023 # be replaced by just "}":
4024 # 1. Some flavor of block following closing parenthesis:
4025 # for (;;) {};
4026 # while (...) {};
4027 # switch (...) {};
4028 # Function(...) {};
4029 # if (...) {};
4030 # if (...) else if (...) {};
4031 #
4032 # 2. else block:
4033 # if (...) else {};
4034 #
4035 # 3. const member function:
4036 # Function(...) const {};
4037 #
4038 # 4. Block following some statement:
4039 # x = 42;
4040 # {};
4041 #
4042 # 5. Block at the beginning of a function:
4043 # Function(...) {
4044 # {};
4045 # }
4046 #
4047 # Note that naively checking for the preceding "{" will also match
4048 # braces inside multi-dimensional arrays, but this is fine since
4049 # that expression will not contain semicolons.
4050 #
4051 # 6. Block following another block:
4052 # while (true) {}
4053 # {};
4054 #
4055 # 7. End of namespaces:
4056 # namespace {};
4057 #
4058 # These semicolons seems far more common than other kinds of
4059 # redundant semicolons, possibly due to people converting classes
4060 # to namespaces. For now we do not warn for this case.
4061 #
4062 # Try matching case 1 first.
4063 match = Match(r'^(.*\)\s*)\{', line)
4064 if match:
4065 # Matched closing parenthesis (case 1). Check the token before the
4066 # matching opening parenthesis, and don't warn if it looks like a
4067 # macro. This avoids these false positives:
4068 # - macro that defines a base class
4069 # - multi-line macro that defines a base class
4070 # - macro that defines the whole class-head
4071 #
4072 # But we still issue warnings for macros that we know are safe to
4073 # warn, specifically:
4074 # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
4075 # - TYPED_TEST
4076 # - INTERFACE_DEF
4077 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
4078 #
4079 # We implement a whitelist of safe macros instead of a blacklist of
4080 # unsafe macros, even though the latter appears less frequently in
4081 # google code and would have been easier to implement. This is because
4082 # the downside for getting the whitelist wrong means some extra
4083 # semicolons, while the downside for getting the blacklist wrong
4084 # would result in compile errors.
4085 #
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004086 # In addition to macros, we also don't want to warn on
4087 # - Compound literals
4088 # - Lambdas
4089 # - alignas specifier with anonymous structs:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004090 closing_brace_pos = match.group(1).rfind(')')
4091 opening_parenthesis = ReverseCloseExpression(
4092 clean_lines, linenum, closing_brace_pos)
4093 if opening_parenthesis[2] > -1:
4094 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
4095 macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004096 func = Match(r'^(.*\])\s*$', line_prefix)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004097 if ((macro and
4098 macro.group(1) not in (
4099 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
4100 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
4101 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004102 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004103 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004104 Search(r'\s+=\s*$', line_prefix)):
4105 match = None
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004106 if (match and
4107 opening_parenthesis[1] > 1 and
4108 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
4109 # Multi-line lambda-expression
4110 match = None
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004111
4112 else:
4113 # Try matching cases 2-3.
4114 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
4115 if not match:
4116 # Try matching cases 4-6. These are always matched on separate lines.
4117 #
4118 # Note that we can't simply concatenate the previous line to the
4119 # current line and do a single match, otherwise we may output
4120 # duplicate warnings for the blank line case:
4121 # if (cond) {
4122 # // blank line
4123 # }
4124 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
4125 if prevline and Search(r'[;{}]\s*$', prevline):
4126 match = Match(r'^(\s*)\{', line)
4127
4128 # Check matching closing brace
4129 if match:
4130 (endline, endlinenum, endpos) = CloseExpression(
4131 clean_lines, linenum, len(match.group(1)))
4132 if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
4133 # Current {} pair is eligible for semicolon check, and we have found
4134 # the redundant semicolon, output warning here.
4135 #
4136 # Note: because we are scanning forward for opening braces, and
4137 # outputting warnings for the matching closing brace, if there are
4138 # nested blocks with trailing semicolons, we will get the error
4139 # messages in reversed order.
4140 error(filename, endlinenum, 'readability/braces', 4,
4141 "You don't need a ; after a }")
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004142
4143
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004144def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
4145 """Look for empty loop/conditional body with only a single semicolon.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004146
4147 Args:
4148 filename: The name of the current file.
4149 clean_lines: A CleansedLines instance containing the file.
4150 linenum: The number of the line to check.
4151 error: The function to call with any errors found.
4152 """
4153
4154 # Search for loop keywords at the beginning of the line. Because only
4155 # whitespaces are allowed before the keywords, this will also ignore most
4156 # do-while-loops, since those lines should start with closing brace.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004157 #
4158 # We also check "if" blocks here, since an empty conditional block
4159 # is likely an error.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004160 line = clean_lines.elided[linenum]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004161 matched = Match(r'\s*(for|while|if)\s*\(', line)
4162 if matched:
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004163 # Find the end of the conditional expression
4164 (end_line, end_linenum, end_pos) = CloseExpression(
4165 clean_lines, linenum, line.find('('))
4166
4167 # Output warning if what follows the condition expression is a semicolon.
4168 # No warning for all other cases, including whitespace or newline, since we
4169 # have a separate check for semicolons preceded by whitespace.
4170 if end_pos >= 0 and Match(r';', end_line[end_pos:]):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004171 if matched.group(1) == 'if':
4172 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
4173 'Empty conditional bodies should use {}')
4174 else:
4175 error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
4176 'Empty loop bodies should use {} or continue')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004177
4178
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004179def FindCheckMacro(line):
4180 """Find a replaceable CHECK-like macro.
4181
4182 Args:
4183 line: line to search on.
4184 Returns:
4185 (macro name, start position), or (None, -1) if no replaceable
4186 macro is found.
4187 """
4188 for macro in _CHECK_MACROS:
4189 i = line.find(macro)
4190 if i >= 0:
4191 # Find opening parenthesis. Do a regular expression match here
4192 # to make sure that we are matching the expected CHECK macro, as
4193 # opposed to some other macro that happens to contain the CHECK
4194 # substring.
4195 matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
4196 if not matched:
4197 continue
4198 return (macro, len(matched.group(1)))
4199 return (None, -1)
4200
4201
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004202def CheckCheck(filename, clean_lines, linenum, error):
4203 """Checks the use of CHECK and EXPECT macros.
4204
4205 Args:
4206 filename: The name of the current file.
4207 clean_lines: A CleansedLines instance containing the file.
4208 linenum: The number of the line to check.
4209 error: The function to call with any errors found.
4210 """
4211
4212 # Decide the set of replacement macros that should be suggested
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004213 lines = clean_lines.elided
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004214 (check_macro, start_pos) = FindCheckMacro(lines[linenum])
4215 if not check_macro:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004216 return
4217
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004218 # Find end of the boolean expression by matching parentheses
4219 (last_line, end_line, end_pos) = CloseExpression(
4220 clean_lines, linenum, start_pos)
4221 if end_pos < 0:
4222 return
avakulenko@google.com59146752014-08-11 20:20:55 +00004223
4224 # If the check macro is followed by something other than a
4225 # semicolon, assume users will log their own custom error messages
4226 # and don't suggest any replacements.
4227 if not Match(r'\s*;', last_line[end_pos:]):
4228 return
4229
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004230 if linenum == end_line:
4231 expression = lines[linenum][start_pos + 1:end_pos - 1]
4232 else:
4233 expression = lines[linenum][start_pos + 1:]
4234 for i in xrange(linenum + 1, end_line):
4235 expression += lines[i]
4236 expression += last_line[0:end_pos - 1]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004237
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004238 # Parse expression so that we can take parentheses into account.
4239 # This avoids false positives for inputs like "CHECK((a < 4) == b)",
4240 # which is not replaceable by CHECK_LE.
4241 lhs = ''
4242 rhs = ''
4243 operator = None
4244 while expression:
4245 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
4246 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4247 if matched:
4248 token = matched.group(1)
4249 if token == '(':
4250 # Parenthesized operand
4251 expression = matched.group(2)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004252 (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004253 if end < 0:
4254 return # Unmatched parenthesis
4255 lhs += '(' + expression[0:end]
4256 expression = expression[end:]
4257 elif token in ('&&', '||'):
4258 # Logical and/or operators. This means the expression
4259 # contains more than one term, for example:
4260 # CHECK(42 < a && a < b);
4261 #
4262 # These are not replaceable with CHECK_LE, so bail out early.
4263 return
4264 elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
4265 # Non-relational operator
4266 lhs += token
4267 expression = matched.group(2)
4268 else:
4269 # Relational operator
4270 operator = token
4271 rhs = matched.group(2)
4272 break
4273 else:
4274 # Unparenthesized operand. Instead of appending to lhs one character
4275 # at a time, we do another regular expression match to consume several
4276 # characters at once if possible. Trivial benchmark shows that this
4277 # is more efficient when the operands are longer than a single
4278 # character, which is generally the case.
4279 matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
4280 if not matched:
4281 matched = Match(r'^(\s*\S)(.*)$', expression)
4282 if not matched:
4283 break
4284 lhs += matched.group(1)
4285 expression = matched.group(2)
4286
4287 # Only apply checks if we got all parts of the boolean expression
4288 if not (lhs and operator and rhs):
4289 return
4290
4291 # Check that rhs do not contain logical operators. We already know
4292 # that lhs is fine since the loop above parses out && and ||.
4293 if rhs.find('&&') > -1 or rhs.find('||') > -1:
4294 return
4295
4296 # At least one of the operands must be a constant literal. This is
4297 # to avoid suggesting replacements for unprintable things like
4298 # CHECK(variable != iterator)
4299 #
4300 # The following pattern matches decimal, hex integers, strings, and
4301 # characters (in that order).
4302 lhs = lhs.strip()
4303 rhs = rhs.strip()
4304 match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
4305 if Match(match_constant, lhs) or Match(match_constant, rhs):
4306 # Note: since we know both lhs and rhs, we can provide a more
4307 # descriptive error message like:
4308 # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
4309 # Instead of:
4310 # Consider using CHECK_EQ instead of CHECK(a == b)
4311 #
4312 # We are still keeping the less descriptive message because if lhs
4313 # or rhs gets long, the error message might become unreadable.
4314 error(filename, linenum, 'readability/check', 2,
4315 'Consider using %s instead of %s(a %s b)' % (
4316 _CHECK_REPLACEMENT[check_macro][operator],
4317 check_macro, operator))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004318
4319
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004320def CheckAltTokens(filename, clean_lines, linenum, error):
4321 """Check alternative keywords being used in boolean expressions.
4322
4323 Args:
4324 filename: The name of the current file.
4325 clean_lines: A CleansedLines instance containing the file.
4326 linenum: The number of the line to check.
4327 error: The function to call with any errors found.
4328 """
4329 line = clean_lines.elided[linenum]
4330
4331 # Avoid preprocessor lines
4332 if Match(r'^\s*#', line):
4333 return
4334
4335 # Last ditch effort to avoid multi-line comments. This will not help
4336 # if the comment started before the current line or ended after the
4337 # current line, but it catches most of the false positives. At least,
4338 # it provides a way to workaround this warning for people who use
4339 # multi-line comments in preprocessor macros.
4340 #
4341 # TODO(unknown): remove this once cpplint has better support for
4342 # multi-line comments.
4343 if line.find('/*') >= 0 or line.find('*/') >= 0:
4344 return
4345
4346 for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4347 error(filename, linenum, 'readability/alt_tokens', 2,
4348 'Use operator %s instead of %s' % (
4349 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4350
4351
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004352def GetLineWidth(line):
4353 """Determines the width of the line in column positions.
4354
4355 Args:
4356 line: A string, which may be a Unicode string.
4357
4358 Returns:
4359 The width of the line in column positions, accounting for Unicode
4360 combining characters and wide characters.
4361 """
4362 if isinstance(line, unicode):
4363 width = 0
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004364 for uc in unicodedata.normalize('NFC', line):
4365 if unicodedata.east_asian_width(uc) in ('W', 'F'):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004366 width += 2
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004367 elif not unicodedata.combining(uc):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004368 width += 1
4369 return width
4370 else:
4371 return len(line)
4372
4373
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004374def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004375 error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004376 """Checks rules from the 'C++ style rules' section of cppguide.html.
4377
4378 Most of these rules are hard to test (naming, comment style), but we
4379 do what we can. In particular we check for 2-space indents, line lengths,
4380 tab usage, spaces inside code, etc.
4381
4382 Args:
4383 filename: The name of the current file.
4384 clean_lines: A CleansedLines instance containing the file.
4385 linenum: The number of the line to check.
4386 file_extension: The extension (without the dot) of the filename.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004387 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004388 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004389 error: The function to call with any errors found.
4390 """
4391
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004392 # Don't use "elided" lines here, otherwise we can't check commented lines.
4393 # Don't want to use "raw" either, because we don't want to check inside C++11
4394 # raw strings,
4395 raw_lines = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004396 line = raw_lines[linenum]
4397
4398 if line.find('\t') != -1:
4399 error(filename, linenum, 'whitespace/tab', 1,
4400 'Tab found; better to use spaces')
4401
4402 # One or three blank spaces at the beginning of the line is weird; it's
4403 # hard to reconcile that with 2-space indents.
4404 # NOTE: here are the conditions rob pike used for his tests. Mine aren't
4405 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
4406 # if(RLENGTH > 20) complain = 0;
4407 # if(match($0, " +(error|private|public|protected):")) complain = 0;
4408 # if(match(prev, "&& *$")) complain = 0;
4409 # if(match(prev, "\\|\\| *$")) complain = 0;
4410 # if(match(prev, "[\",=><] *$")) complain = 0;
4411 # if(match($0, " <<")) complain = 0;
4412 # if(match(prev, " +for \\(")) complain = 0;
4413 # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004414 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
4415 classinfo = nesting_state.InnermostClass()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004416 initial_spaces = 0
4417 cleansed_line = clean_lines.elided[linenum]
4418 while initial_spaces < len(line) and line[initial_spaces] == ' ':
4419 initial_spaces += 1
4420 if line and line[-1].isspace():
4421 error(filename, linenum, 'whitespace/end_of_line', 4,
4422 'Line ends in whitespace. Consider deleting these extra spaces.')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004423 # There are certain situations we allow one space, notably for
4424 # section labels, and also lines containing multi-line raw strings.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004425 elif ((initial_spaces == 1 or initial_spaces == 3) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004426 not Match(scope_or_label_pattern, cleansed_line) and
4427 not (clean_lines.raw_lines[linenum] != line and
4428 Match(r'^\s*""', line))):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004429 error(filename, linenum, 'whitespace/indent', 3,
4430 'Weird number of spaces at line-start. '
4431 'Are you using a 2-space indent?')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004432
4433 # Check if the line is a header guard.
4434 is_header_guard = False
4435 if file_extension == 'h':
4436 cppvar = GetHeaderGuardCPPVariable(filename)
4437 if (line.startswith('#ifndef %s' % cppvar) or
4438 line.startswith('#define %s' % cppvar) or
4439 line.startswith('#endif // %s' % cppvar)):
4440 is_header_guard = True
4441 # #include lines and header guards can be long, since there's no clean way to
4442 # split them.
erg@google.com6317a9c2009-06-25 00:28:19 +00004443 #
4444 # URLs can be long too. It's possible to split these, but it makes them
4445 # harder to cut&paste.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004446 #
4447 # The "$Id:...$" comment may also get very long without it being the
4448 # developers fault.
erg@google.com6317a9c2009-06-25 00:28:19 +00004449 if (not line.startswith('#include') and not is_header_guard and
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004450 not Match(r'^\s*//.*http(s?)://\S*$', line) and
4451 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004452 line_width = GetLineWidth(line)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004453 extended_length = int((_line_length * 1.25))
4454 if line_width > extended_length:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004455 error(filename, linenum, 'whitespace/line_length', 4,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004456 'Lines should very rarely be longer than %i characters' %
4457 extended_length)
4458 elif line_width > _line_length:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004459 error(filename, linenum, 'whitespace/line_length', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004460 'Lines should be <= %i characters long' % _line_length)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004461
4462 if (cleansed_line.count(';') > 1 and
4463 # for loops are allowed two ;'s (and may run over two lines).
4464 cleansed_line.find('for') == -1 and
4465 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
4466 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
4467 # It's ok to have many commands in a switch case that fits in 1 line
4468 not ((cleansed_line.find('case ') != -1 or
4469 cleansed_line.find('default:') != -1) and
4470 cleansed_line.find('break;') != -1)):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004471 error(filename, linenum, 'whitespace/newline', 0,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004472 'More than one command on the same line')
4473
4474 # Some more style checks
4475 CheckBraces(filename, clean_lines, linenum, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004476 CheckTrailingSemicolon(filename, clean_lines, linenum, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004477 CheckEmptyBlockBody(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004478 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
4479 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004480 CheckOperatorSpacing(filename, clean_lines, linenum, error)
4481 CheckParenthesisSpacing(filename, clean_lines, linenum, error)
4482 CheckCommaSpacing(filename, clean_lines, linenum, error)
4483 CheckBracesSpacing(filename, clean_lines, linenum, error)
4484 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
4485 CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004486 CheckCheck(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004487 CheckAltTokens(filename, clean_lines, linenum, error)
4488 classinfo = nesting_state.InnermostClass()
4489 if classinfo:
4490 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004491
4492
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004493_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4494# Matches the first component of a filename delimited by -s and _s. That is:
4495# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
4496# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
4497# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
4498# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
4499_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
4500
4501
4502def _DropCommonSuffixes(filename):
4503 """Drops common suffixes like _test.cc or -inl.h from filename.
4504
4505 For example:
4506 >>> _DropCommonSuffixes('foo/foo-inl.h')
4507 'foo/foo'
4508 >>> _DropCommonSuffixes('foo/bar/foo.cc')
4509 'foo/bar/foo'
4510 >>> _DropCommonSuffixes('foo/foo_internal.h')
4511 'foo/foo'
4512 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
4513 'foo/foo_unusualinternal'
4514
4515 Args:
4516 filename: The input filename.
4517
4518 Returns:
4519 The filename with the common suffix removed.
4520 """
4521 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
4522 'inl.h', 'impl.h', 'internal.h'):
4523 if (filename.endswith(suffix) and len(filename) > len(suffix) and
4524 filename[-len(suffix) - 1] in ('-', '_')):
4525 return filename[:-len(suffix) - 1]
4526 return os.path.splitext(filename)[0]
4527
4528
4529def _IsTestFilename(filename):
4530 """Determines if the given filename has a suffix that identifies it as a test.
4531
4532 Args:
4533 filename: The input filename.
4534
4535 Returns:
4536 True if 'filename' looks like a test, False otherwise.
4537 """
4538 if (filename.endswith('_test.cc') or
4539 filename.endswith('_unittest.cc') or
4540 filename.endswith('_regtest.cc')):
4541 return True
4542 else:
4543 return False
4544
4545
4546def _ClassifyInclude(fileinfo, include, is_system):
4547 """Figures out what kind of header 'include' is.
4548
4549 Args:
4550 fileinfo: The current file cpplint is running over. A FileInfo instance.
4551 include: The path to a #included file.
4552 is_system: True if the #include used <> rather than "".
4553
4554 Returns:
4555 One of the _XXX_HEADER constants.
4556
4557 For example:
4558 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
4559 _C_SYS_HEADER
4560 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
4561 _CPP_SYS_HEADER
4562 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
4563 _LIKELY_MY_HEADER
4564 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
4565 ... 'bar/foo_other_ext.h', False)
4566 _POSSIBLE_MY_HEADER
4567 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
4568 _OTHER_HEADER
4569 """
4570 # This is a list of all standard c++ header files, except
4571 # those already checked for above.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004572 is_cpp_h = include in _CPP_HEADERS
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004573
4574 if is_system:
4575 if is_cpp_h:
4576 return _CPP_SYS_HEADER
4577 else:
4578 return _C_SYS_HEADER
4579
4580 # If the target file and the include we're checking share a
4581 # basename when we drop common extensions, and the include
4582 # lives in . , then it's likely to be owned by the target file.
4583 target_dir, target_base = (
4584 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
4585 include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
4586 if target_base == include_base and (
4587 include_dir == target_dir or
4588 include_dir == os.path.normpath(target_dir + '/../public')):
4589 return _LIKELY_MY_HEADER
4590
4591 # If the target and include share some initial basename
4592 # component, it's possible the target is implementing the
4593 # include, so it's allowed to be first, but we'll never
4594 # complain if it's not there.
4595 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4596 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4597 if (target_first_component and include_first_component and
4598 target_first_component.group(0) ==
4599 include_first_component.group(0)):
4600 return _POSSIBLE_MY_HEADER
4601
4602 return _OTHER_HEADER
4603
4604
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004605
erg@google.com6317a9c2009-06-25 00:28:19 +00004606def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
4607 """Check rules that are applicable to #include lines.
4608
4609 Strings on #include lines are NOT removed from elided line, to make
4610 certain tasks easier. However, to prevent false positives, checks
4611 applicable to #include lines in CheckLanguage must be put here.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004612
4613 Args:
4614 filename: The name of the current file.
4615 clean_lines: A CleansedLines instance containing the file.
4616 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004617 include_state: An _IncludeState instance in which the headers are inserted.
4618 error: The function to call with any errors found.
4619 """
4620 fileinfo = FileInfo(filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00004621 line = clean_lines.lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004622
4623 # "include" should use the new style "foo/bar.h" instead of just "bar.h"
avakulenko@google.com59146752014-08-11 20:20:55 +00004624 # Only do this check if the included header follows google naming
4625 # conventions. If not, assume that it's a 3rd party API that
4626 # requires special include conventions.
4627 #
4628 # We also make an exception for Lua headers, which follow google
4629 # naming convention but not the include convention.
4630 match = Match(r'#include\s*"([^/]+\.h)"', line)
4631 if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004632 error(filename, linenum, 'build/include', 4,
4633 'Include the directory when naming .h files')
4634
4635 # we shouldn't include a file more than once. actually, there are a
4636 # handful of instances where doing so is okay, but in general it's
4637 # not.
erg@google.com6317a9c2009-06-25 00:28:19 +00004638 match = _RE_PATTERN_INCLUDE.search(line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004639 if match:
4640 include = match.group(2)
4641 is_system = (match.group(1) == '<')
avakulenko@google.com59146752014-08-11 20:20:55 +00004642 duplicate_line = include_state.FindHeader(include)
4643 if duplicate_line >= 0:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004644 error(filename, linenum, 'build/include', 4,
4645 '"%s" already included at %s:%s' %
avakulenko@google.com59146752014-08-11 20:20:55 +00004646 (include, filename, duplicate_line))
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004647 elif (include.endswith('.cc') and
4648 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4649 error(filename, linenum, 'build/include', 4,
4650 'Do not include .cc files from other packages')
avakulenko@google.com59146752014-08-11 20:20:55 +00004651 elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4652 include_state.include_list[-1].append((include, linenum))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004653
4654 # We want to ensure that headers appear in the right order:
4655 # 1) for foo.cc, foo.h (preferred location)
4656 # 2) c system files
4657 # 3) cpp system files
4658 # 4) for foo.cc, foo.h (deprecated location)
4659 # 5) other google headers
4660 #
4661 # We classify each include statement as one of those 5 types
4662 # using a number of techniques. The include_state object keeps
4663 # track of the highest type seen, and complains if we see a
4664 # lower type after that.
4665 error_message = include_state.CheckNextIncludeOrder(
4666 _ClassifyInclude(fileinfo, include, is_system))
4667 if error_message:
4668 error(filename, linenum, 'build/include_order', 4,
4669 '%s. Should be: %s.h, c system, c++ system, other.' %
4670 (error_message, fileinfo.BaseName()))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004671 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4672 if not include_state.IsInAlphabeticalOrder(
4673 clean_lines, linenum, canonical_include):
erg@google.com26970fa2009-11-17 18:07:32 +00004674 error(filename, linenum, 'build/include_alpha', 4,
4675 'Include "%s" not in alphabetical order' % include)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004676 include_state.SetLastHeader(canonical_include)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004677
erg@google.com6317a9c2009-06-25 00:28:19 +00004678
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004679
4680def _GetTextInside(text, start_pattern):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004681 r"""Retrieves all the text between matching open and close parentheses.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004682
4683 Given a string of lines and a regular expression string, retrieve all the text
4684 following the expression and between opening punctuation symbols like
4685 (, [, or {, and the matching close-punctuation symbol. This properly nested
4686 occurrences of the punctuations, so for the text like
4687 printf(a(), b(c()));
4688 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
4689 start_pattern must match string having an open punctuation symbol at the end.
4690
4691 Args:
4692 text: The lines to extract text. Its comments and strings must be elided.
4693 It can be single line and can span multiple lines.
4694 start_pattern: The regexp string indicating where to start extracting
4695 the text.
4696 Returns:
4697 The extracted text.
4698 None if either the opening string or ending punctuation could not be found.
4699 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004700 # TODO(unknown): Audit cpplint.py to see what places could be profitably
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004701 # rewritten to use _GetTextInside (and use inferior regexp matching today).
4702
4703 # Give opening punctuations to get the matching close-punctuations.
4704 matching_punctuation = {'(': ')', '{': '}', '[': ']'}
4705 closing_punctuation = set(matching_punctuation.itervalues())
4706
4707 # Find the position to start extracting text.
4708 match = re.search(start_pattern, text, re.M)
4709 if not match: # start_pattern not found in text.
4710 return None
4711 start_position = match.end(0)
4712
4713 assert start_position > 0, (
4714 'start_pattern must ends with an opening punctuation.')
4715 assert text[start_position - 1] in matching_punctuation, (
4716 'start_pattern must ends with an opening punctuation.')
4717 # Stack of closing punctuations we expect to have in text after position.
4718 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4719 position = start_position
4720 while punctuation_stack and position < len(text):
4721 if text[position] == punctuation_stack[-1]:
4722 punctuation_stack.pop()
4723 elif text[position] in closing_punctuation:
4724 # A closing punctuation without matching opening punctuations.
4725 return None
4726 elif text[position] in matching_punctuation:
4727 punctuation_stack.append(matching_punctuation[text[position]])
4728 position += 1
4729 if punctuation_stack:
4730 # Opening punctuations left without matching close-punctuations.
4731 return None
4732 # punctuations match.
4733 return text[start_position:position - 1]
4734
4735
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004736# Patterns for matching call-by-reference parameters.
4737#
4738# Supports nested templates up to 2 levels deep using this messy pattern:
4739# < (?: < (?: < [^<>]*
4740# >
4741# | [^<>] )*
4742# >
4743# | [^<>] )*
4744# >
4745_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
4746_RE_PATTERN_TYPE = (
4747 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
4748 r'(?:\w|'
4749 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
4750 r'::)+')
4751# A call-by-reference parameter ends with '& identifier'.
4752_RE_PATTERN_REF_PARAM = re.compile(
4753 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
4754 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
4755# A call-by-const-reference parameter either ends with 'const& identifier'
4756# or looks like 'const type& identifier' when 'type' is atomic.
4757_RE_PATTERN_CONST_REF_PARAM = (
4758 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4759 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
4760
4761
4762def CheckLanguage(filename, clean_lines, linenum, file_extension,
4763 include_state, nesting_state, error):
erg@google.com6317a9c2009-06-25 00:28:19 +00004764 """Checks rules from the 'C++ language rules' section of cppguide.html.
4765
4766 Some of these rules are hard to test (function overloading, using
4767 uint32 inappropriately), but we do the best we can.
4768
4769 Args:
4770 filename: The name of the current file.
4771 clean_lines: A CleansedLines instance containing the file.
4772 linenum: The number of the line to check.
4773 file_extension: The extension (without the dot) of the filename.
4774 include_state: An _IncludeState instance in which the headers are inserted.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004775 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004776 the current stack of nested blocks being parsed.
erg@google.com6317a9c2009-06-25 00:28:19 +00004777 error: The function to call with any errors found.
4778 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004779 # If the line is empty or consists of entirely a comment, no need to
4780 # check it.
4781 line = clean_lines.elided[linenum]
4782 if not line:
4783 return
4784
erg@google.com6317a9c2009-06-25 00:28:19 +00004785 match = _RE_PATTERN_INCLUDE.search(line)
4786 if match:
4787 CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
4788 return
4789
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004790 # Reset include state across preprocessor directives. This is meant
4791 # to silence warnings for conditional includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00004792 match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4793 if match:
4794 include_state.ResetSection(match.group(1))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004795
4796 # Make Windows paths like Unix.
4797 fullname = os.path.abspath(filename).replace('\\', '/')
skym@chromium.org3990c412016-02-05 20:55:12 +00004798
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004799 # Perform other checks now that we are sure that this is not an include line
4800 CheckCasts(filename, clean_lines, linenum, error)
4801 CheckGlobalStatic(filename, clean_lines, linenum, error)
4802 CheckPrintf(filename, clean_lines, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004803
4804 if file_extension == 'h':
4805 # TODO(unknown): check that 1-arg constructors are explicit.
4806 # How to tell it's a constructor?
4807 # (handled in CheckForNonStandardConstructs for now)
avakulenko@google.com59146752014-08-11 20:20:55 +00004808 # TODO(unknown): check that classes declare or disable copy/assign
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004809 # (level 1 error)
4810 pass
4811
4812 # Check if people are using the verboten C basic types. The only exception
4813 # we regularly allow is "unsigned short port" for port.
4814 if Search(r'\bshort port\b', line):
4815 if not Search(r'\bunsigned short port\b', line):
4816 error(filename, linenum, 'runtime/int', 4,
4817 'Use "unsigned short" for ports, not "short"')
4818 else:
4819 match = Search(r'\b(short|long(?! +double)|long long)\b', line)
4820 if match:
4821 error(filename, linenum, 'runtime/int', 4,
4822 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4823
erg@google.com26970fa2009-11-17 18:07:32 +00004824 # Check if some verboten operator overloading is going on
4825 # TODO(unknown): catch out-of-line unary operator&:
4826 # class X {};
4827 # int operator&(const X& x) { return 42; } // unary operator&
4828 # The trick is it's hard to tell apart from binary operator&:
4829 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
4830 if Search(r'\boperator\s*&\s*\(\s*\)', line):
4831 error(filename, linenum, 'runtime/operator', 4,
4832 'Unary operator& is dangerous. Do not use it.')
4833
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004834 # Check for suspicious usage of "if" like
4835 # } if (a == b) {
4836 if Search(r'\}\s*if\s*\(', line):
4837 error(filename, linenum, 'readability/braces', 4,
4838 'Did you mean "else if"? If not, start a new line for "if".')
4839
4840 # Check for potential format string bugs like printf(foo).
4841 # We constrain the pattern not to pick things like DocidForPrintf(foo).
4842 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004843 # TODO(unknown): Catch the following case. Need to change the calling
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004844 # convention of the whole function to process multiple line to handle it.
4845 # printf(
4846 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
4847 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
4848 if printf_args:
4849 match = Match(r'([\w.\->()]+)$', printf_args)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004850 if match and match.group(1) != '__VA_ARGS__':
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004851 function_name = re.search(r'\b((?:string)?printf)\s*\(',
4852 line, re.I).group(1)
4853 error(filename, linenum, 'runtime/printf', 4,
4854 'Potential format string bug. Do %s("%%s", %s) instead.'
4855 % (function_name, match.group(1)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004856
4857 # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
4858 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4859 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4860 error(filename, linenum, 'runtime/memset', 4,
4861 'Did you mean "memset(%s, 0, %s)"?'
4862 % (match.group(1), match.group(2)))
4863
4864 if Search(r'\busing namespace\b', line):
4865 error(filename, linenum, 'build/namespaces', 5,
4866 'Do not use namespace using-directives. '
4867 'Use using-declarations instead.')
4868
4869 # Detect variable-length arrays.
4870 match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4871 if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
4872 match.group(3).find(']') == -1):
4873 # Split the size using space and arithmetic operators as delimiters.
4874 # If any of the resulting tokens are not compile time constants then
4875 # report the error.
4876 tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4877 is_const = True
4878 skip_next = False
4879 for tok in tokens:
4880 if skip_next:
4881 skip_next = False
4882 continue
4883
4884 if Search(r'sizeof\(.+\)', tok): continue
4885 if Search(r'arraysize\(\w+\)', tok): continue
4886
4887 tok = tok.lstrip('(')
4888 tok = tok.rstrip(')')
4889 if not tok: continue
4890 if Match(r'\d+', tok): continue
4891 if Match(r'0[xX][0-9a-fA-F]+', tok): continue
4892 if Match(r'k[A-Z0-9]\w*', tok): continue
4893 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
4894 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
4895 # A catch all for tricky sizeof cases, including 'sizeof expression',
4896 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004897 # requires skipping the next token because we split on ' ' and '*'.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004898 if tok.startswith('sizeof'):
4899 skip_next = True
4900 continue
4901 is_const = False
4902 break
4903 if not is_const:
4904 error(filename, linenum, 'runtime/arrays', 1,
4905 'Do not use variable-length arrays. Use an appropriately named '
4906 "('k' followed by CamelCase) compile-time constant for the size.")
4907
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004908 # Check for use of unnamed namespaces in header files. Registration
4909 # macros are typically OK, so we allow use of "namespace {" on lines
4910 # that end with backslashes.
4911 if (file_extension == 'h'
4912 and Search(r'\bnamespace\s*{', line)
4913 and line[-1] != '\\'):
4914 error(filename, linenum, 'build/namespaces', 4,
4915 'Do not use unnamed namespaces in header files. See '
4916 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
4917 ' for more information.')
4918
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004919
4920def CheckGlobalStatic(filename, clean_lines, linenum, error):
4921 """Check for unsafe global or static objects.
4922
4923 Args:
4924 filename: The name of the current file.
4925 clean_lines: A CleansedLines instance containing the file.
4926 linenum: The number of the line to check.
4927 error: The function to call with any errors found.
4928 """
4929 line = clean_lines.elided[linenum]
4930
avakulenko@google.com59146752014-08-11 20:20:55 +00004931 # Match two lines at a time to support multiline declarations
4932 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
4933 line += clean_lines.elided[linenum + 1].strip()
4934
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004935 # Check for people declaring static/global STL strings at the top level.
4936 # This is dangerous because the C++ language does not guarantee that
4937 # globals with constructors are initialized before the first access.
4938 match = Match(
4939 r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
4940 line)
avakulenko@google.com59146752014-08-11 20:20:55 +00004941
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004942 # Remove false positives:
4943 # - String pointers (as opposed to values).
4944 # string *pointer
4945 # const string *pointer
4946 # string const *pointer
4947 # string *const pointer
4948 #
4949 # - Functions and template specializations.
4950 # string Function<Type>(...
4951 # string Class<Type>::Method(...
4952 #
4953 # - Operators. These are matched separately because operator names
4954 # cross non-word boundaries, and trying to match both operators
4955 # and functions at the same time would decrease accuracy of
4956 # matching identifiers.
4957 # string Class::operator*()
4958 if (match and
4959 not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and
4960 not Search(r'\boperator\W', line) and
avakulenko@google.com59146752014-08-11 20:20:55 +00004961 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004962 error(filename, linenum, 'runtime/string', 4,
4963 'For a static/global string constant, use a C style string instead: '
4964 '"%schar %s[]".' %
4965 (match.group(1), match.group(2)))
4966
4967 if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
4968 error(filename, linenum, 'runtime/init', 4,
4969 'You seem to be initializing a member variable with itself.')
4970
4971
4972def CheckPrintf(filename, clean_lines, linenum, error):
4973 """Check for printf related issues.
4974
4975 Args:
4976 filename: The name of the current file.
4977 clean_lines: A CleansedLines instance containing the file.
4978 linenum: The number of the line to check.
4979 error: The function to call with any errors found.
4980 """
4981 line = clean_lines.elided[linenum]
4982
4983 # When snprintf is used, the second argument shouldn't be a literal.
4984 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
4985 if match and match.group(2) != '0':
4986 # If 2nd arg is zero, snprintf is used to calculate size.
4987 error(filename, linenum, 'runtime/printf', 3,
4988 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
4989 'to snprintf.' % (match.group(1), match.group(2)))
4990
4991 # Check if some verboten C functions are being used.
avakulenko@google.com59146752014-08-11 20:20:55 +00004992 if Search(r'\bsprintf\s*\(', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004993 error(filename, linenum, 'runtime/printf', 5,
4994 'Never use sprintf. Use snprintf instead.')
avakulenko@google.com59146752014-08-11 20:20:55 +00004995 match = Search(r'\b(strcpy|strcat)\s*\(', line)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004996 if match:
4997 error(filename, linenum, 'runtime/printf', 4,
4998 'Almost always, snprintf is better than %s' % match.group(1))
4999
5000
5001def IsDerivedFunction(clean_lines, linenum):
5002 """Check if current line contains an inherited function.
5003
5004 Args:
5005 clean_lines: A CleansedLines instance containing the file.
5006 linenum: The number of the line to check.
5007 Returns:
5008 True if current line contains a function with "override"
5009 virt-specifier.
5010 """
avakulenko@google.com59146752014-08-11 20:20:55 +00005011 # Scan back a few lines for start of current function
5012 for i in xrange(linenum, max(-1, linenum - 10), -1):
5013 match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
5014 if match:
5015 # Look for "override" after the matching closing parenthesis
5016 line, _, closing_paren = CloseExpression(
5017 clean_lines, i, len(match.group(1)))
5018 return (closing_paren >= 0 and
5019 Search(r'\boverride\b', line[closing_paren:]))
5020 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005021
5022
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005023def IsOutOfLineMethodDefinition(clean_lines, linenum):
5024 """Check if current line contains an out-of-line method definition.
5025
5026 Args:
5027 clean_lines: A CleansedLines instance containing the file.
5028 linenum: The number of the line to check.
5029 Returns:
5030 True if current line contains an out-of-line method definition.
5031 """
5032 # Scan back a few lines for start of current function
5033 for i in xrange(linenum, max(-1, linenum - 10), -1):
5034 if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
5035 return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
5036 return False
5037
5038
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005039def IsInitializerList(clean_lines, linenum):
5040 """Check if current line is inside constructor initializer list.
5041
5042 Args:
5043 clean_lines: A CleansedLines instance containing the file.
5044 linenum: The number of the line to check.
5045 Returns:
5046 True if current line appears to be inside constructor initializer
5047 list, False otherwise.
5048 """
5049 for i in xrange(linenum, 1, -1):
5050 line = clean_lines.elided[i]
5051 if i == linenum:
5052 remove_function_body = Match(r'^(.*)\{\s*$', line)
5053 if remove_function_body:
5054 line = remove_function_body.group(1)
5055
5056 if Search(r'\s:\s*\w+[({]', line):
5057 # A lone colon tend to indicate the start of a constructor
5058 # initializer list. It could also be a ternary operator, which
5059 # also tend to appear in constructor initializer lists as
5060 # opposed to parameter lists.
5061 return True
5062 if Search(r'\}\s*,\s*$', line):
5063 # A closing brace followed by a comma is probably the end of a
5064 # brace-initialized member in constructor initializer list.
5065 return True
5066 if Search(r'[{};]\s*$', line):
5067 # Found one of the following:
5068 # - A closing brace or semicolon, probably the end of the previous
5069 # function.
5070 # - An opening brace, probably the start of current class or namespace.
5071 #
5072 # Current line is probably not inside an initializer list since
5073 # we saw one of those things without seeing the starting colon.
5074 return False
5075
5076 # Got to the beginning of the file without seeing the start of
5077 # constructor initializer list.
5078 return False
5079
5080
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005081def CheckForNonConstReference(filename, clean_lines, linenum,
5082 nesting_state, error):
5083 """Check for non-const references.
5084
5085 Separate from CheckLanguage since it scans backwards from current
5086 line, instead of scanning forward.
5087
5088 Args:
5089 filename: The name of the current file.
5090 clean_lines: A CleansedLines instance containing the file.
5091 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005092 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005093 the current stack of nested blocks being parsed.
5094 error: The function to call with any errors found.
5095 """
5096 # Do nothing if there is no '&' on current line.
5097 line = clean_lines.elided[linenum]
5098 if '&' not in line:
5099 return
5100
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005101 # If a function is inherited, current function doesn't have much of
5102 # a choice, so any non-const references should not be blamed on
5103 # derived function.
5104 if IsDerivedFunction(clean_lines, linenum):
5105 return
5106
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005107 # Don't warn on out-of-line method definitions, as we would warn on the
5108 # in-line declaration, if it isn't marked with 'override'.
5109 if IsOutOfLineMethodDefinition(clean_lines, linenum):
5110 return
5111
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005112 # Long type names may be broken across multiple lines, usually in one
5113 # of these forms:
5114 # LongType
5115 # ::LongTypeContinued &identifier
5116 # LongType::
5117 # LongTypeContinued &identifier
5118 # LongType<
5119 # ...>::LongTypeContinued &identifier
5120 #
5121 # If we detected a type split across two lines, join the previous
5122 # line to current line so that we can match const references
5123 # accordingly.
5124 #
5125 # Note that this only scans back one line, since scanning back
5126 # arbitrary number of lines would be expensive. If you have a type
5127 # that spans more than 2 lines, please use a typedef.
5128 if linenum > 1:
5129 previous = None
5130 if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5131 # previous_line\n + ::current_line
5132 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5133 clean_lines.elided[linenum - 1])
5134 elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5135 # previous_line::\n + current_line
5136 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5137 clean_lines.elided[linenum - 1])
5138 if previous:
5139 line = previous.group(1) + line.lstrip()
5140 else:
5141 # Check for templated parameter that is split across multiple lines
5142 endpos = line.rfind('>')
5143 if endpos > -1:
5144 (_, startline, startpos) = ReverseCloseExpression(
5145 clean_lines, linenum, endpos)
5146 if startpos > -1 and startline < linenum:
5147 # Found the matching < on an earlier line, collect all
5148 # pieces up to current line.
5149 line = ''
5150 for i in xrange(startline, linenum + 1):
5151 line += clean_lines.elided[i].strip()
5152
5153 # Check for non-const references in function parameters. A single '&' may
5154 # found in the following places:
5155 # inside expression: binary & for bitwise AND
5156 # inside expression: unary & for taking the address of something
5157 # inside declarators: reference parameter
5158 # We will exclude the first two cases by checking that we are not inside a
5159 # function body, including one that was just introduced by a trailing '{'.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005160 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005161 if (nesting_state.previous_stack_top and
5162 not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
5163 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5164 # Not at toplevel, not within a class, and not within a namespace
5165 return
5166
avakulenko@google.com59146752014-08-11 20:20:55 +00005167 # Avoid initializer lists. We only need to scan back from the
5168 # current line for something that starts with ':'.
5169 #
5170 # We don't need to check the current line, since the '&' would
5171 # appear inside the second set of parentheses on the current line as
5172 # opposed to the first set.
5173 if linenum > 0:
5174 for i in xrange(linenum - 1, max(0, linenum - 10), -1):
5175 previous_line = clean_lines.elided[i]
5176 if not Search(r'[),]\s*$', previous_line):
5177 break
5178 if Match(r'^\s*:\s+\S', previous_line):
5179 return
5180
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005181 # Avoid preprocessors
5182 if Search(r'\\\s*$', line):
5183 return
5184
5185 # Avoid constructor initializer lists
5186 if IsInitializerList(clean_lines, linenum):
5187 return
5188
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005189 # We allow non-const references in a few standard places, like functions
5190 # called "swap()" or iostream operators like "<<" or ">>". Do not check
5191 # those function parameters.
5192 #
5193 # We also accept & in static_assert, which looks like a function but
5194 # it's actually a declaration expression.
5195 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
5196 r'operator\s*[<>][<>]|'
5197 r'static_assert|COMPILE_ASSERT'
5198 r')\s*\(')
5199 if Search(whitelisted_functions, line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005200 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005201 elif not Search(r'\S+\([^)]*$', line):
5202 # Don't see a whitelisted function on this line. Actually we
5203 # didn't see any function name on this line, so this is likely a
5204 # multi-line parameter list. Try a bit harder to catch this case.
5205 for i in xrange(2):
5206 if (linenum > i and
5207 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005208 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005209
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005210 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
5211 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
5212 if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
5213 error(filename, linenum, 'runtime/references', 2,
5214 'Is this a non-const reference? '
5215 'If so, make const or use a pointer: ' +
5216 ReplaceAll(' *<', '<', parameter))
5217
5218
5219def CheckCasts(filename, clean_lines, linenum, error):
5220 """Various cast related checks.
5221
5222 Args:
5223 filename: The name of the current file.
5224 clean_lines: A CleansedLines instance containing the file.
5225 linenum: The number of the line to check.
5226 error: The function to call with any errors found.
5227 """
5228 line = clean_lines.elided[linenum]
5229
5230 # Check to see if they're using an conversion function cast.
5231 # I just try to capture the most common basic types, though there are more.
5232 # Parameterless conversion functions, such as bool(), are allowed as they are
5233 # probably a member operator declaration or default constructor.
5234 match = Search(
5235 r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b'
5236 r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
5237 r'(\([^)].*)', line)
5238 expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
5239 if match and not expecting_function:
5240 matched_type = match.group(2)
5241
5242 # matched_new_or_template is used to silence two false positives:
5243 # - New operators
5244 # - Template arguments with function types
5245 #
5246 # For template arguments, we match on types immediately following
5247 # an opening bracket without any spaces. This is a fast way to
5248 # silence the common case where the function type is the first
5249 # template argument. False negative with less-than comparison is
5250 # avoided because those operators are usually followed by a space.
5251 #
5252 # function<double(double)> // bracket + no space = false positive
5253 # value < double(42) // bracket + space = true positive
5254 matched_new_or_template = match.group(1)
5255
avakulenko@google.com59146752014-08-11 20:20:55 +00005256 # Avoid arrays by looking for brackets that come after the closing
5257 # parenthesis.
5258 if Match(r'\([^()]+\)\s*\[', match.group(3)):
5259 return
5260
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005261 # Other things to ignore:
5262 # - Function pointers
5263 # - Casts to pointer types
5264 # - Placement new
5265 # - Alias declarations
5266 matched_funcptr = match.group(3)
5267 if (matched_new_or_template is None and
5268 not (matched_funcptr and
5269 (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5270 matched_funcptr) or
5271 matched_funcptr.startswith('(*)'))) and
5272 not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
5273 not Search(r'new\(\S+\)\s*' + matched_type, line)):
5274 error(filename, linenum, 'readability/casting', 4,
5275 'Using deprecated casting style. '
5276 'Use static_cast<%s>(...) instead' %
5277 matched_type)
5278
5279 if not expecting_function:
avakulenko@google.com59146752014-08-11 20:20:55 +00005280 CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005281 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5282
5283 # This doesn't catch all cases. Consider (const char * const)"hello".
5284 #
5285 # (char *) "foo" should always be a const_cast (reinterpret_cast won't
5286 # compile).
avakulenko@google.com59146752014-08-11 20:20:55 +00005287 if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
5288 r'\((char\s?\*+\s?)\)\s*"', error):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005289 pass
5290 else:
5291 # Check pointer casts for other than string constants
avakulenko@google.com59146752014-08-11 20:20:55 +00005292 CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
5293 r'\((\w+\s?\*+\s?)\)', error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005294
5295 # In addition, we look for people taking the address of a cast. This
5296 # is dangerous -- casts can assign to temporaries, so the pointer doesn't
5297 # point where you think.
avakulenko@google.com59146752014-08-11 20:20:55 +00005298 #
5299 # Some non-identifier character is required before the '&' for the
5300 # expression to be recognized as a cast. These are casts:
5301 # expression = &static_cast<int*>(temporary());
5302 # function(&(int*)(temporary()));
5303 #
5304 # This is not a cast:
5305 # reference_type&(int* function_param);
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005306 match = Search(
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005307 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
avakulenko@google.com59146752014-08-11 20:20:55 +00005308 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005309 if match:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005310 # Try a better error message when the & is bound to something
5311 # dereferenced by the casted pointer, as opposed to the casted
5312 # pointer itself.
5313 parenthesis_error = False
5314 match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5315 if match:
5316 _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
5317 if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
5318 _, y2, x2 = CloseExpression(clean_lines, y1, x1)
5319 if x2 >= 0:
5320 extended_line = clean_lines.elided[y2][x2:]
5321 if y2 < clean_lines.NumLines() - 1:
5322 extended_line += clean_lines.elided[y2 + 1]
5323 if Match(r'\s*(?:->|\[)', extended_line):
5324 parenthesis_error = True
5325
5326 if parenthesis_error:
5327 error(filename, linenum, 'readability/casting', 4,
5328 ('Are you taking an address of something dereferenced '
5329 'from a cast? Wrapping the dereferenced expression in '
5330 'parentheses will make the binding more obvious'))
5331 else:
5332 error(filename, linenum, 'runtime/casting', 4,
5333 ('Are you taking an address of a cast? '
5334 'This is dangerous: could be a temp var. '
5335 'Take the address before doing the cast, rather than after'))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005336
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005337
avakulenko@google.com59146752014-08-11 20:20:55 +00005338def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005339 """Checks for a C-style cast by looking for the pattern.
5340
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005341 Args:
5342 filename: The name of the current file.
avakulenko@google.com59146752014-08-11 20:20:55 +00005343 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005344 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005345 cast_type: The string for the C++ cast to recommend. This is either
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005346 reinterpret_cast, static_cast, or const_cast, depending.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005347 pattern: The regular expression used to find C-style casts.
5348 error: The function to call with any errors found.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005349
5350 Returns:
5351 True if an error was emitted.
5352 False otherwise.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005353 """
avakulenko@google.com59146752014-08-11 20:20:55 +00005354 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005355 match = Search(pattern, line)
5356 if not match:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005357 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005358
avakulenko@google.com59146752014-08-11 20:20:55 +00005359 # Exclude lines with keywords that tend to look like casts
5360 context = line[0:match.start(1) - 1]
5361 if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5362 return False
5363
5364 # Try expanding current context to see if we one level of
5365 # parentheses inside a macro.
5366 if linenum > 0:
5367 for i in xrange(linenum - 1, max(0, linenum - 5), -1):
5368 context = clean_lines.elided[i] + context
5369 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005370 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005371
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005372 # operator++(int) and operator--(int)
avakulenko@google.com59146752014-08-11 20:20:55 +00005373 if context.endswith(' operator++') or context.endswith(' operator--'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005374 return False
5375
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005376 # A single unnamed argument for a function tends to look like old
5377 # style cast. If we see those, don't issue warnings for deprecated
5378 # casts, instead issue warnings for unnamed arguments where
5379 # appropriate.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005380 #
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005381 # These are things that we want warnings for, since the style guide
5382 # explicitly require all parameters to be named:
5383 # Function(int);
5384 # Function(int) {
5385 # ConstMember(int) const;
5386 # ConstMember(int) const {
5387 # ExceptionMember(int) throw (...);
5388 # ExceptionMember(int) throw (...) {
5389 # PureVirtual(int) = 0;
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005390 # [](int) -> bool {
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005391 #
5392 # These are functions of some sort, where the compiler would be fine
5393 # if they had named parameters, but people often omit those
5394 # identifiers to reduce clutter:
5395 # (FunctionPointer)(int);
5396 # (FunctionPointer)(int) = value;
5397 # Function((function_pointer_arg)(int))
avakulenko@google.com59146752014-08-11 20:20:55 +00005398 # Function((function_pointer_arg)(int), int param)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005399 # <TemplateArgument(int)>;
5400 # <(FunctionPointerTemplateArgument)(int)>;
5401 remainder = line[match.end(0):]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005402 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005403 remainder):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005404 # Looks like an unnamed parameter.
5405
5406 # Don't warn on any kind of template arguments.
5407 if Match(r'^\s*>', remainder):
5408 return False
5409
5410 # Don't warn on assignments to function pointers, but keep warnings for
5411 # unnamed parameters to pure virtual functions. Note that this pattern
5412 # will also pass on assignments of "0" to function pointers, but the
5413 # preferred values for those would be "nullptr" or "NULL".
5414 matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder)
5415 if matched_zero and matched_zero.group(1) != '0':
5416 return False
5417
5418 # Don't warn on function pointer declarations. For this we need
5419 # to check what came before the "(type)" string.
5420 if Match(r'.*\)\s*$', line[0:match.start(0)]):
5421 return False
5422
5423 # Don't warn if the parameter is named with block comments, e.g.:
5424 # Function(int /*unused_param*/);
avakulenko@google.com59146752014-08-11 20:20:55 +00005425 raw_line = clean_lines.raw_lines[linenum]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005426 if '/*' in raw_line:
5427 return False
5428
5429 # Passed all filters, issue warning here.
5430 error(filename, linenum, 'readability/function', 3,
5431 'All parameters should be named in a function')
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005432 return True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005433
5434 # At this point, all that should be left is actual casts.
5435 error(filename, linenum, 'readability/casting', 4,
5436 'Using C-style cast. Use %s<%s>(...) instead' %
5437 (cast_type, match.group(1)))
5438
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005439 return True
5440
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005441
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005442def ExpectingFunctionArgs(clean_lines, linenum):
5443 """Checks whether where function type arguments are expected.
5444
5445 Args:
5446 clean_lines: A CleansedLines instance containing the file.
5447 linenum: The number of the line to check.
5448
5449 Returns:
5450 True if the line at 'linenum' is inside something that expects arguments
5451 of function types.
5452 """
5453 line = clean_lines.elided[linenum]
5454 return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
5455 (linenum >= 2 and
5456 (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5457 clean_lines.elided[linenum - 1]) or
5458 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5459 clean_lines.elided[linenum - 2]) or
5460 Search(r'\bstd::m?function\s*\<\s*$',
5461 clean_lines.elided[linenum - 1]))))
5462
5463
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005464_HEADERS_CONTAINING_TEMPLATES = (
5465 ('<deque>', ('deque',)),
5466 ('<functional>', ('unary_function', 'binary_function',
5467 'plus', 'minus', 'multiplies', 'divides', 'modulus',
5468 'negate',
5469 'equal_to', 'not_equal_to', 'greater', 'less',
5470 'greater_equal', 'less_equal',
5471 'logical_and', 'logical_or', 'logical_not',
5472 'unary_negate', 'not1', 'binary_negate', 'not2',
5473 'bind1st', 'bind2nd',
5474 'pointer_to_unary_function',
5475 'pointer_to_binary_function',
5476 'ptr_fun',
5477 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
5478 'mem_fun_ref_t',
5479 'const_mem_fun_t', 'const_mem_fun1_t',
5480 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
5481 'mem_fun_ref',
5482 )),
5483 ('<limits>', ('numeric_limits',)),
5484 ('<list>', ('list',)),
5485 ('<map>', ('map', 'multimap',)),
5486 ('<memory>', ('allocator',)),
5487 ('<queue>', ('queue', 'priority_queue',)),
5488 ('<set>', ('set', 'multiset',)),
5489 ('<stack>', ('stack',)),
5490 ('<string>', ('char_traits', 'basic_string',)),
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005491 ('<tuple>', ('tuple',)),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005492 ('<utility>', ('pair',)),
5493 ('<vector>', ('vector',)),
5494
5495 # gcc extensions.
5496 # Note: std::hash is their hash, ::hash is our hash
5497 ('<hash_map>', ('hash_map', 'hash_multimap',)),
5498 ('<hash_set>', ('hash_set', 'hash_multiset',)),
5499 ('<slist>', ('slist',)),
5500 )
5501
skym@chromium.org3990c412016-02-05 20:55:12 +00005502_HEADERS_MAYBE_TEMPLATES = (
5503 ('<algorithm>', ('copy', 'max', 'min', 'min_element', 'sort',
5504 'transform',
5505 )),
5506 ('<utility>', ('swap',)),
5507 )
5508
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005509_RE_PATTERN_STRING = re.compile(r'\bstring\b')
5510
skym@chromium.org3990c412016-02-05 20:55:12 +00005511_re_pattern_headers_maybe_templates = []
5512for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
5513 for _template in _templates:
5514 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
5515 # type::max().
5516 _re_pattern_headers_maybe_templates.append(
5517 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
5518 _template,
5519 _header))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005520
skym@chromium.org3990c412016-02-05 20:55:12 +00005521# Other scripts may reach in and modify this pattern.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005522_re_pattern_templates = []
5523for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
5524 for _template in _templates:
5525 _re_pattern_templates.append(
5526 (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
5527 _template + '<>',
5528 _header))
5529
5530
erg@google.com6317a9c2009-06-25 00:28:19 +00005531def FilesBelongToSameModule(filename_cc, filename_h):
5532 """Check if these two filenames belong to the same module.
5533
5534 The concept of a 'module' here is a as follows:
5535 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
5536 same 'module' if they are in the same directory.
5537 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
5538 to belong to the same module here.
5539
5540 If the filename_cc contains a longer path than the filename_h, for example,
5541 '/absolute/path/to/base/sysinfo.cc', and this file would include
5542 'base/sysinfo.h', this function also produces the prefix needed to open the
5543 header. This is used by the caller of this function to more robustly open the
5544 header file. We don't have access to the real include paths in this context,
5545 so we need this guesswork here.
5546
5547 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
5548 according to this implementation. Because of this, this function gives
5549 some false positives. This should be sufficiently rare in practice.
5550
5551 Args:
5552 filename_cc: is the path for the .cc file
5553 filename_h: is the path for the header path
5554
5555 Returns:
5556 Tuple with a bool and a string:
5557 bool: True if filename_cc and filename_h belong to the same module.
5558 string: the additional prefix needed to open the header file.
5559 """
5560
5561 if not filename_cc.endswith('.cc'):
5562 return (False, '')
5563 filename_cc = filename_cc[:-len('.cc')]
5564 if filename_cc.endswith('_unittest'):
5565 filename_cc = filename_cc[:-len('_unittest')]
5566 elif filename_cc.endswith('_test'):
5567 filename_cc = filename_cc[:-len('_test')]
5568 filename_cc = filename_cc.replace('/public/', '/')
5569 filename_cc = filename_cc.replace('/internal/', '/')
5570
5571 if not filename_h.endswith('.h'):
5572 return (False, '')
5573 filename_h = filename_h[:-len('.h')]
5574 if filename_h.endswith('-inl'):
5575 filename_h = filename_h[:-len('-inl')]
5576 filename_h = filename_h.replace('/public/', '/')
5577 filename_h = filename_h.replace('/internal/', '/')
5578
5579 files_belong_to_same_module = filename_cc.endswith(filename_h)
5580 common_path = ''
5581 if files_belong_to_same_module:
5582 common_path = filename_cc[:-len(filename_h)]
5583 return files_belong_to_same_module, common_path
5584
5585
avakulenko@google.com59146752014-08-11 20:20:55 +00005586def UpdateIncludeState(filename, include_dict, io=codecs):
5587 """Fill up the include_dict with new includes found from the file.
erg@google.com6317a9c2009-06-25 00:28:19 +00005588
5589 Args:
5590 filename: the name of the header to read.
avakulenko@google.com59146752014-08-11 20:20:55 +00005591 include_dict: a dictionary in which the headers are inserted.
erg@google.com6317a9c2009-06-25 00:28:19 +00005592 io: The io factory to use to read the file. Provided for testability.
5593
5594 Returns:
avakulenko@google.com59146752014-08-11 20:20:55 +00005595 True if a header was successfully added. False otherwise.
erg@google.com6317a9c2009-06-25 00:28:19 +00005596 """
5597 headerfile = None
5598 try:
5599 headerfile = io.open(filename, 'r', 'utf8', 'replace')
5600 except IOError:
5601 return False
5602 linenum = 0
5603 for line in headerfile:
5604 linenum += 1
5605 clean_line = CleanseComments(line)
5606 match = _RE_PATTERN_INCLUDE.search(clean_line)
5607 if match:
5608 include = match.group(2)
avakulenko@google.com59146752014-08-11 20:20:55 +00005609 include_dict.setdefault(include, linenum)
erg@google.com6317a9c2009-06-25 00:28:19 +00005610 return True
5611
5612
5613def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
5614 io=codecs):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005615 """Reports for missing stl includes.
5616
5617 This function will output warnings to make sure you are including the headers
5618 necessary for the stl containers and functions that you use. We only give one
5619 reason to include a header. For example, if you use both equal_to<> and
5620 less<> in a .h file, only one (the latter in the file) of these will be
5621 reported as a reason to include the <functional>.
5622
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005623 Args:
5624 filename: The name of the current file.
5625 clean_lines: A CleansedLines instance containing the file.
5626 include_state: An _IncludeState instance.
5627 error: The function to call with any errors found.
erg@google.com6317a9c2009-06-25 00:28:19 +00005628 io: The IO factory to use to read the header file. Provided for unittest
5629 injection.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005630 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005631 required = {} # A map of header name to linenumber and the template entity.
5632 # Example of required: { '<functional>': (1219, 'less<>') }
5633
5634 for linenum in xrange(clean_lines.NumLines()):
5635 line = clean_lines.elided[linenum]
5636 if not line or line[0] == '#':
5637 continue
5638
5639 # String is special -- it is a non-templatized type in STL.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005640 matched = _RE_PATTERN_STRING.search(line)
5641 if matched:
erg@google.com35589e62010-11-17 18:58:16 +00005642 # Don't warn about strings in non-STL namespaces:
5643 # (We check only the first match per line; good enough.)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005644 prefix = line[:matched.start()]
erg@google.com35589e62010-11-17 18:58:16 +00005645 if prefix.endswith('std::') or not prefix.endswith('::'):
5646 required['<string>'] = (linenum, 'string')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005647
skym@chromium.org3990c412016-02-05 20:55:12 +00005648 for pattern, template, header in _re_pattern_headers_maybe_templates:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005649 if pattern.search(line):
5650 required[header] = (linenum, template)
5651
5652 # The following function is just a speed up, no semantics are changed.
5653 if not '<' in line: # Reduces the cpu time usage by skipping lines.
5654 continue
5655
5656 for pattern, template, header in _re_pattern_templates:
5657 if pattern.search(line):
5658 required[header] = (linenum, template)
5659
erg@google.com6317a9c2009-06-25 00:28:19 +00005660 # The policy is that if you #include something in foo.h you don't need to
5661 # include it again in foo.cc. Here, we will look at possible includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00005662 # Let's flatten the include_state include_list and copy it into a dictionary.
5663 include_dict = dict([item for sublist in include_state.include_list
5664 for item in sublist])
erg@google.com6317a9c2009-06-25 00:28:19 +00005665
avakulenko@google.com59146752014-08-11 20:20:55 +00005666 # Did we find the header for this file (if any) and successfully load it?
erg@google.com6317a9c2009-06-25 00:28:19 +00005667 header_found = False
5668
5669 # Use the absolute path so that matching works properly.
erg@chromium.org8f927562012-01-30 19:51:28 +00005670 abs_filename = FileInfo(filename).FullName()
erg@google.com6317a9c2009-06-25 00:28:19 +00005671
5672 # For Emacs's flymake.
5673 # If cpplint is invoked from Emacs's flymake, a temporary file is generated
5674 # by flymake and that file name might end with '_flymake.cc'. In that case,
5675 # restore original file name here so that the corresponding header file can be
5676 # found.
5677 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
5678 # instead of 'foo_flymake.h'
erg@google.com35589e62010-11-17 18:58:16 +00005679 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00005680
avakulenko@google.com59146752014-08-11 20:20:55 +00005681 # include_dict is modified during iteration, so we iterate over a copy of
erg@google.com6317a9c2009-06-25 00:28:19 +00005682 # the keys.
avakulenko@google.com59146752014-08-11 20:20:55 +00005683 header_keys = include_dict.keys()
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005684 for header in header_keys:
erg@google.com6317a9c2009-06-25 00:28:19 +00005685 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
5686 fullpath = common_path + header
avakulenko@google.com59146752014-08-11 20:20:55 +00005687 if same_module and UpdateIncludeState(fullpath, include_dict, io):
erg@google.com6317a9c2009-06-25 00:28:19 +00005688 header_found = True
5689
5690 # If we can't find the header file for a .cc, assume it's because we don't
5691 # know where to look. In that case we'll give up as we're not sure they
5692 # didn't include it in the .h file.
5693 # TODO(unknown): Do a better job of finding .h files so we are confident that
5694 # not having the .h file means there isn't one.
5695 if filename.endswith('.cc') and not header_found:
5696 return
5697
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005698 # All the lines have been processed, report the errors found.
5699 for required_header_unstripped in required:
5700 template = required[required_header_unstripped][1]
avakulenko@google.com59146752014-08-11 20:20:55 +00005701 if required_header_unstripped.strip('<>"') not in include_dict:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005702 error(filename, required[required_header_unstripped][0],
5703 'build/include_what_you_use', 4,
5704 'Add #include ' + required_header_unstripped + ' for ' + template)
5705
5706
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005707_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
5708
5709
5710def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
5711 """Check that make_pair's template arguments are deduced.
5712
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005713 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005714 specified explicitly, and such use isn't intended in any case.
5715
5716 Args:
5717 filename: The name of the current file.
5718 clean_lines: A CleansedLines instance containing the file.
5719 linenum: The number of the line to check.
5720 error: The function to call with any errors found.
5721 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005722 line = clean_lines.elided[linenum]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005723 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5724 if match:
5725 error(filename, linenum, 'build/explicit_make_pair',
5726 4, # 4 = high confidence
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005727 'For C++11-compatibility, omit template arguments from make_pair'
5728 ' OR use pair directly OR if appropriate, construct a pair directly')
avakulenko@google.com59146752014-08-11 20:20:55 +00005729
5730
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005731def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error):
5732 """Check that default lambda captures are not used.
5733
5734 Args:
5735 filename: The name of the current file.
5736 clean_lines: A CleansedLines instance containing the file.
5737 linenum: The number of the line to check.
5738 error: The function to call with any errors found.
5739 """
5740 line = clean_lines.elided[linenum]
5741
5742 # A lambda introducer specifies a default capture if it starts with "[="
5743 # or if it starts with "[&" _not_ followed by an identifier.
5744 match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line)
5745 if match:
5746 # Found a potential error, check what comes after the lambda-introducer.
5747 # If it's not open parenthesis (for lambda-declarator) or open brace
5748 # (for compound-statement), it's not a lambda.
5749 line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1)))
5750 if pos >= 0 and Match(r'^\s*[{(]', line[pos:]):
5751 error(filename, linenum, 'build/c++11',
5752 4, # 4 = high confidence
5753 'Default lambda captures are an unapproved C++ feature.')
5754
5755
avakulenko@google.com59146752014-08-11 20:20:55 +00005756def CheckRedundantVirtual(filename, clean_lines, linenum, error):
5757 """Check if line contains a redundant "virtual" function-specifier.
5758
5759 Args:
5760 filename: The name of the current file.
5761 clean_lines: A CleansedLines instance containing the file.
5762 linenum: The number of the line to check.
5763 error: The function to call with any errors found.
5764 """
5765 # Look for "virtual" on current line.
5766 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005767 virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
avakulenko@google.com59146752014-08-11 20:20:55 +00005768 if not virtual: return
5769
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005770 # Ignore "virtual" keywords that are near access-specifiers. These
5771 # are only used in class base-specifier and do not apply to member
5772 # functions.
5773 if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
5774 Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
5775 return
5776
5777 # Ignore the "virtual" keyword from virtual base classes. Usually
5778 # there is a column on the same line in these cases (virtual base
5779 # classes are rare in google3 because multiple inheritance is rare).
5780 if Match(r'^.*[^:]:[^:].*$', line): return
5781
avakulenko@google.com59146752014-08-11 20:20:55 +00005782 # Look for the next opening parenthesis. This is the start of the
5783 # parameter list (possibly on the next line shortly after virtual).
5784 # TODO(unknown): doesn't work if there are virtual functions with
5785 # decltype() or other things that use parentheses, but csearch suggests
5786 # that this is rare.
5787 end_col = -1
5788 end_line = -1
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005789 start_col = len(virtual.group(2))
avakulenko@google.com59146752014-08-11 20:20:55 +00005790 for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
5791 line = clean_lines.elided[start_line][start_col:]
5792 parameter_list = Match(r'^([^(]*)\(', line)
5793 if parameter_list:
5794 # Match parentheses to find the end of the parameter list
5795 (_, end_line, end_col) = CloseExpression(
5796 clean_lines, start_line, start_col + len(parameter_list.group(1)))
5797 break
5798 start_col = 0
5799
5800 if end_col < 0:
5801 return # Couldn't find end of parameter list, give up
5802
5803 # Look for "override" or "final" after the parameter list
5804 # (possibly on the next few lines).
5805 for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
5806 line = clean_lines.elided[i][end_col:]
5807 match = Search(r'\b(override|final)\b', line)
5808 if match:
5809 error(filename, linenum, 'readability/inheritance', 4,
5810 ('"virtual" is redundant since function is '
5811 'already declared as "%s"' % match.group(1)))
5812
5813 # Set end_col to check whole lines after we are done with the
5814 # first line.
5815 end_col = 0
5816 if Search(r'[^\w]\s*$', line):
5817 break
5818
5819
5820def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
5821 """Check if line contains a redundant "override" or "final" virt-specifier.
5822
5823 Args:
5824 filename: The name of the current file.
5825 clean_lines: A CleansedLines instance containing the file.
5826 linenum: The number of the line to check.
5827 error: The function to call with any errors found.
5828 """
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005829 # Look for closing parenthesis nearby. We need one to confirm where
5830 # the declarator ends and where the virt-specifier starts to avoid
5831 # false positives.
avakulenko@google.com59146752014-08-11 20:20:55 +00005832 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005833 declarator_end = line.rfind(')')
5834 if declarator_end >= 0:
5835 fragment = line[declarator_end:]
5836 else:
5837 if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
5838 fragment = line
5839 else:
5840 return
5841
5842 # Check that at most one of "override" or "final" is present, not both
5843 if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
avakulenko@google.com59146752014-08-11 20:20:55 +00005844 error(filename, linenum, 'readability/inheritance', 4,
5845 ('"override" is redundant since function is '
5846 'already declared as "final"'))
5847
5848
5849
5850
5851# Returns true if we are at a new block, and it is directly
5852# inside of a namespace.
5853def IsBlockInNameSpace(nesting_state, is_forward_declaration):
5854 """Checks that the new block is directly in a namespace.
5855
5856 Args:
5857 nesting_state: The _NestingState object that contains info about our state.
5858 is_forward_declaration: If the class is a forward declared class.
5859 Returns:
5860 Whether or not the new block is directly in a namespace.
5861 """
5862 if is_forward_declaration:
5863 if len(nesting_state.stack) >= 1 and (
5864 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
5865 return True
5866 else:
5867 return False
5868
5869 return (len(nesting_state.stack) > 1 and
5870 nesting_state.stack[-1].check_namespace_indentation and
5871 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5872
5873
5874def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
5875 raw_lines_no_comments, linenum):
5876 """This method determines if we should apply our namespace indentation check.
5877
5878 Args:
5879 nesting_state: The current nesting state.
5880 is_namespace_indent_item: If we just put a new class on the stack, True.
5881 If the top of the stack is not a class, or we did not recently
5882 add the class, False.
5883 raw_lines_no_comments: The lines without the comments.
5884 linenum: The current line number we are processing.
5885
5886 Returns:
5887 True if we should apply our namespace indentation check. Currently, it
5888 only works for classes and namespaces inside of a namespace.
5889 """
5890
5891 is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
5892 linenum)
5893
5894 if not (is_namespace_indent_item or is_forward_declaration):
5895 return False
5896
5897 # If we are in a macro, we do not want to check the namespace indentation.
5898 if IsMacroDefinition(raw_lines_no_comments, linenum):
5899 return False
5900
5901 return IsBlockInNameSpace(nesting_state, is_forward_declaration)
5902
5903
5904# Call this method if the line is directly inside of a namespace.
5905# If the line above is blank (excluding comments) or the start of
5906# an inner namespace, it cannot be indented.
5907def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
5908 error):
5909 line = raw_lines_no_comments[linenum]
5910 if Match(r'^\s+', line):
5911 error(filename, linenum, 'runtime/indentation_namespace', 4,
5912 'Do not indent within a namespace')
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005913
5914
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005915def ProcessLine(filename, file_extension, clean_lines, line,
5916 include_state, function_state, nesting_state, error,
5917 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005918 """Processes a single line in the file.
5919
5920 Args:
5921 filename: Filename of the file that is being processed.
5922 file_extension: The extension (dot not included) of the file.
5923 clean_lines: An array of strings, each representing a line of the file,
5924 with comments stripped.
5925 line: Number of line being processed.
5926 include_state: An _IncludeState instance in which the headers are inserted.
5927 function_state: A _FunctionState instance which counts function lines, etc.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005928 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005929 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005930 error: A callable to which errors are reported, which takes 4 arguments:
5931 filename, line number, error level, and message
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005932 extra_check_functions: An array of additional check functions that will be
5933 run on each source line. Each function takes 4
5934 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005935 """
5936 raw_lines = clean_lines.raw_lines
erg@google.com35589e62010-11-17 18:58:16 +00005937 ParseNolintSuppressions(filename, raw_lines[line], line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005938 nesting_state.Update(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005939 CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
5940 error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005941 if nesting_state.InAsmBlock(): return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005942 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005943 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005944 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005945 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005946 nesting_state, error)
5947 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005948 CheckForNonStandardConstructs(filename, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005949 nesting_state, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005950 CheckVlogArguments(filename, clean_lines, line, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005951 CheckPosixThreading(filename, clean_lines, line, error)
erg@google.com6317a9c2009-06-25 00:28:19 +00005952 CheckInvalidIncrement(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005953 CheckMakePairUsesDeduction(filename, clean_lines, line, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005954 CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005955 CheckRedundantVirtual(filename, clean_lines, line, error)
5956 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005957 for check_fn in extra_check_functions:
5958 check_fn(filename, clean_lines, line, error)
avakulenko@google.com17449932014-07-28 22:13:33 +00005959
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005960def FlagCxx11Features(filename, clean_lines, linenum, error):
5961 """Flag those c++11 features that we only allow in certain places.
5962
5963 Args:
5964 filename: The name of the current file.
5965 clean_lines: A CleansedLines instance containing the file.
5966 linenum: The number of the line to check.
5967 error: The function to call with any errors found.
5968 """
5969 line = clean_lines.elided[linenum]
5970
5971 # Flag unapproved C++11 headers.
5972 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5973 if include and include.group(1) in ('cfenv',
5974 'condition_variable',
5975 'fenv.h',
5976 'future',
5977 'mutex',
5978 'thread',
5979 'chrono',
5980 'ratio',
5981 'regex',
5982 'system_error',
5983 ):
5984 error(filename, linenum, 'build/c++11', 5,
5985 ('<%s> is an unapproved C++11 header.') % include.group(1))
5986
5987 # The only place where we need to worry about C++11 keywords and library
5988 # features in preprocessor directives is in macro definitions.
5989 if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
5990
5991 # These are classes and free functions. The classes are always
5992 # mentioned as std::*, but we only catch the free functions if
5993 # they're not found by ADL. They're alphabetical by header.
5994 for top_name in (
5995 # type_traits
5996 'alignment_of',
5997 'aligned_union',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005998 ):
5999 if Search(r'\bstd::%s\b' % top_name, line):
6000 error(filename, linenum, 'build/c++11', 5,
6001 ('std::%s is an unapproved C++11 class or function. Send c-style '
6002 'an example of where it would make your code more readable, and '
6003 'they may let you use it.') % top_name)
6004
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006005
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006006def ProcessFileData(filename, file_extension, lines, error,
6007 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006008 """Performs lint checks and reports any errors to the given error function.
6009
6010 Args:
6011 filename: Filename of the file that is being processed.
6012 file_extension: The extension (dot not included) of the file.
6013 lines: An array of strings, each representing a line of the file, with the
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006014 last element being empty if the file is terminated with a newline.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006015 error: A callable to which errors are reported, which takes 4 arguments:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006016 filename, line number, error level, and message
6017 extra_check_functions: An array of additional check functions that will be
6018 run on each source line. Each function takes 4
6019 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006020 """
6021 lines = (['// marker so line numbers and indices both start at 1'] + lines +
6022 ['// marker so line numbers end in a known way'])
6023
6024 include_state = _IncludeState()
6025 function_state = _FunctionState()
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006026 nesting_state = NestingState()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006027
erg@google.com35589e62010-11-17 18:58:16 +00006028 ResetNolintSuppressions()
6029
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006030 CheckForCopyright(filename, lines, error)
6031
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006032 RemoveMultiLineComments(filename, lines, error)
6033 clean_lines = CleansedLines(lines)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00006034
6035 if file_extension == 'h':
6036 CheckForHeaderGuard(filename, clean_lines, error)
6037
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006038 for line in xrange(clean_lines.NumLines()):
6039 ProcessLine(filename, file_extension, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006040 include_state, function_state, nesting_state, error,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006041 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006042 FlagCxx11Features(filename, clean_lines, line, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006043 nesting_state.CheckCompletedBlocks(filename, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006044
6045 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
skym@chromium.org3990c412016-02-05 20:55:12 +00006046
avakulenko@google.com255f2be2014-12-05 22:19:55 +00006047 # Check that the .cc file has included its header if it exists.
6048 if file_extension == 'cc':
6049 CheckHeaderFileIncluded(filename, include_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006050
6051 # We check here rather than inside ProcessLine so that we see raw
6052 # lines rather than "cleaned" lines.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006053 CheckForBadCharacters(filename, lines, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006054
6055 CheckForNewlineAtEOF(filename, lines, error)
6056
avakulenko@google.com17449932014-07-28 22:13:33 +00006057def ProcessConfigOverrides(filename):
6058 """ Loads the configuration files and processes the config overrides.
6059
6060 Args:
6061 filename: The name of the file being processed by the linter.
6062
6063 Returns:
6064 False if the current |filename| should not be processed further.
6065 """
6066
6067 abs_filename = os.path.abspath(filename)
6068 cfg_filters = []
6069 keep_looking = True
6070 while keep_looking:
6071 abs_path, base_name = os.path.split(abs_filename)
6072 if not base_name:
6073 break # Reached the root directory.
6074
6075 cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
6076 abs_filename = abs_path
6077 if not os.path.isfile(cfg_file):
6078 continue
6079
6080 try:
6081 with open(cfg_file) as file_handle:
6082 for line in file_handle:
6083 line, _, _ = line.partition('#') # Remove comments.
6084 if not line.strip():
6085 continue
6086
6087 name, _, val = line.partition('=')
6088 name = name.strip()
6089 val = val.strip()
6090 if name == 'set noparent':
6091 keep_looking = False
6092 elif name == 'filter':
6093 cfg_filters.append(val)
6094 elif name == 'exclude_files':
6095 # When matching exclude_files pattern, use the base_name of
6096 # the current file name or the directory name we are processing.
6097 # For example, if we are checking for lint errors in /foo/bar/baz.cc
6098 # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
6099 # file's "exclude_files" filter is meant to be checked against "bar"
6100 # and not "baz" nor "bar/baz.cc".
6101 if base_name:
6102 pattern = re.compile(val)
6103 if pattern.match(base_name):
6104 sys.stderr.write('Ignoring "%s": file excluded by "%s". '
6105 'File path component "%s" matches '
6106 'pattern "%s"\n' %
6107 (filename, cfg_file, base_name, val))
6108 return False
avakulenko@google.com68a4fa62014-08-25 16:26:18 +00006109 elif name == 'linelength':
6110 global _line_length
6111 try:
6112 _line_length = int(val)
6113 except ValueError:
6114 sys.stderr.write('Line length must be numeric.')
avakulenko@google.com17449932014-07-28 22:13:33 +00006115 else:
6116 sys.stderr.write(
6117 'Invalid configuration option (%s) in file %s\n' %
6118 (name, cfg_file))
6119
6120 except IOError:
6121 sys.stderr.write(
6122 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
6123 keep_looking = False
6124
6125 # Apply all the accumulated filters in reverse order (top-level directory
6126 # config options having the least priority).
6127 for filter in reversed(cfg_filters):
6128 _AddFilters(filter)
6129
6130 return True
6131
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006132
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006133def ProcessFile(filename, vlevel, extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006134 """Does google-lint on a single file.
6135
6136 Args:
6137 filename: The name of the file to parse.
6138
6139 vlevel: The level of errors to report. Every error of confidence
6140 >= verbose_level will be reported. 0 is a good default.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006141
6142 extra_check_functions: An array of additional check functions that will be
6143 run on each source line. Each function takes 4
6144 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006145 """
6146
6147 _SetVerboseLevel(vlevel)
avakulenko@google.com17449932014-07-28 22:13:33 +00006148 _BackupFilters()
6149
6150 if not ProcessConfigOverrides(filename):
6151 _RestoreFilters()
6152 return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006153
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006154 lf_lines = []
6155 crlf_lines = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006156 try:
6157 # Support the UNIX convention of using "-" for stdin. Note that
6158 # we are not opening the file with universal newline support
6159 # (which codecs doesn't support anyway), so the resulting lines do
6160 # contain trailing '\r' characters if we are reading a file that
6161 # has CRLF endings.
6162 # If after the split a trailing '\r' is present, it is removed
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006163 # below.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006164 if filename == '-':
6165 lines = codecs.StreamReaderWriter(sys.stdin,
6166 codecs.getreader('utf8'),
6167 codecs.getwriter('utf8'),
6168 'replace').read().split('\n')
6169 else:
6170 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
6171
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006172 # Remove trailing '\r'.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006173 # The -1 accounts for the extra trailing blank line we get from split()
6174 for linenum in range(len(lines) - 1):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006175 if lines[linenum].endswith('\r'):
6176 lines[linenum] = lines[linenum].rstrip('\r')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006177 crlf_lines.append(linenum + 1)
6178 else:
6179 lf_lines.append(linenum + 1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006180
6181 except IOError:
6182 sys.stderr.write(
6183 "Skipping input '%s': Can't open for reading\n" % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00006184 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006185 return
6186
6187 # Note, if no dot is found, this will give the entire filename as the ext.
6188 file_extension = filename[filename.rfind('.') + 1:]
6189
6190 # When reading from stdin, the extension is unknown, so no cpplint tests
6191 # should rely on the extension.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006192 if filename != '-' and file_extension not in _valid_extensions:
6193 sys.stderr.write('Ignoring %s; not a valid file name '
6194 '(%s)\n' % (filename, ', '.join(_valid_extensions)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006195 else:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00006196 ProcessFileData(filename, file_extension, lines, Error,
6197 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00006198
6199 # If end-of-line sequences are a mix of LF and CR-LF, issue
6200 # warnings on the lines with CR.
6201 #
6202 # Don't issue any warnings if all lines are uniformly LF or CR-LF,
6203 # since critique can handle these just fine, and the style guide
6204 # doesn't dictate a particular end of line sequence.
6205 #
6206 # We can't depend on os.linesep to determine what the desired
6207 # end-of-line sequence should be, since that will return the
6208 # server-side end-of-line sequence.
6209 if lf_lines and crlf_lines:
6210 # Warn on every line with CR. An alternative approach might be to
6211 # check whether the file is mostly CRLF or just LF, and warn on the
6212 # minority, we bias toward LF here since most tools prefer LF.
6213 for linenum in crlf_lines:
6214 Error(filename, linenum, 'whitespace/newline', 1,
6215 'Unexpected \\r (^M) found; better to use only \\n')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006216
6217 sys.stderr.write('Done processing %s\n' % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00006218 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006219
6220
6221def PrintUsage(message):
6222 """Prints a brief usage string and exits, optionally with an error message.
6223
6224 Args:
6225 message: The optional error message.
6226 """
6227 sys.stderr.write(_USAGE)
6228 if message:
6229 sys.exit('\nFATAL ERROR: ' + message)
6230 else:
6231 sys.exit(1)
6232
6233
6234def PrintCategories():
6235 """Prints a list of all the error-categories used by error messages.
6236
6237 These are the categories used to filter messages via --filter.
6238 """
erg@google.com35589e62010-11-17 18:58:16 +00006239 sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006240 sys.exit(0)
6241
6242
6243def ParseArguments(args):
6244 """Parses the command line arguments.
6245
6246 This may set the output format and verbosity level as side-effects.
6247
6248 Args:
6249 args: The command line arguments:
6250
6251 Returns:
6252 The list of filenames to lint.
6253 """
6254 try:
6255 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
erg@google.com26970fa2009-11-17 18:07:32 +00006256 'counting=',
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006257 'filter=',
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006258 'root=',
6259 'linelength=',
6260 'extensions='])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006261 except getopt.GetoptError:
6262 PrintUsage('Invalid arguments.')
6263
6264 verbosity = _VerboseLevel()
6265 output_format = _OutputFormat()
6266 filters = ''
erg@google.com26970fa2009-11-17 18:07:32 +00006267 counting_style = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006268
6269 for (opt, val) in opts:
6270 if opt == '--help':
6271 PrintUsage(None)
6272 elif opt == '--output':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006273 if val not in ('emacs', 'vs7', 'eclipse'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006274 PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006275 output_format = val
6276 elif opt == '--verbose':
6277 verbosity = int(val)
6278 elif opt == '--filter':
6279 filters = val
erg@google.com6317a9c2009-06-25 00:28:19 +00006280 if not filters:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006281 PrintCategories()
erg@google.com26970fa2009-11-17 18:07:32 +00006282 elif opt == '--counting':
6283 if val not in ('total', 'toplevel', 'detailed'):
6284 PrintUsage('Valid counting options are total, toplevel, and detailed')
6285 counting_style = val
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006286 elif opt == '--root':
6287 global _root
6288 _root = val
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006289 elif opt == '--linelength':
6290 global _line_length
6291 try:
6292 _line_length = int(val)
6293 except ValueError:
6294 PrintUsage('Line length must be digits.')
6295 elif opt == '--extensions':
6296 global _valid_extensions
6297 try:
6298 _valid_extensions = set(val.split(','))
6299 except ValueError:
6300 PrintUsage('Extensions must be comma seperated list.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006301
6302 if not filenames:
6303 PrintUsage('No files were specified.')
6304
6305 _SetOutputFormat(output_format)
6306 _SetVerboseLevel(verbosity)
6307 _SetFilters(filters)
erg@google.com26970fa2009-11-17 18:07:32 +00006308 _SetCountingStyle(counting_style)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006309
6310 return filenames
6311
6312
6313def main():
6314 filenames = ParseArguments(sys.argv[1:])
6315
6316 # Change stderr to write with replacement characters so we don't die
6317 # if we try to print something containing non-ASCII characters.
6318 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
6319 codecs.getreader('utf8'),
6320 codecs.getwriter('utf8'),
6321 'replace')
6322
erg@google.com26970fa2009-11-17 18:07:32 +00006323 _cpplint_state.ResetErrorCounts()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006324 for filename in filenames:
6325 ProcessFile(filename, _cpplint_state.verbose_level)
erg@google.com26970fa2009-11-17 18:07:32 +00006326 _cpplint_state.PrintErrorCounts()
6327
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006328 sys.exit(_cpplint_state.error_count > 0)
6329
6330
6331if __name__ == '__main__':
6332 main()