blob: 670c285565e7371390c3630f8ae746e9352a9f4f [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
agablef39c3332016-09-26 09:35:42 -070031# pylint: skip-file
32
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000033"""Does google-lint on c++ files.
34
35The goal of this script is to identify places in the code that *may*
36be in non-compliance with google style. It does not attempt to fix
37up these problems -- the point is to educate. It does also not
38attempt to find all problems, or to ensure that everything it does
39find is legitimately a problem.
40
41In particular, we can get very confused by /* and // inside strings!
42We do a small hack, which is to ignore //'s with "'s after them on the
43same line, but it is far from perfect (in either direction).
44"""
45
46import codecs
mazda@chromium.org3fffcec2013-06-07 01:04:53 +000047import copy
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000048import getopt
49import math # for log
50import os
51import re
52import sre_compile
53import string
54import sys
55import unicodedata
56
57
58_USAGE = """
59Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +000060 [--counting=total|toplevel|detailed] [--root=subdir]
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +000061 [--linelength=digits]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000062 <file> [file] ...
63
64 The style guidelines this tries to follow are those in
Alexandr Ilinff294c32017-04-27 15:57:40 +020065 https://google.github.io/styleguide/cppguide.html
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000066
67 Every problem is given a confidence score from 1-5, with 5 meaning we are
68 certain of the problem, and 1 meaning it could be a legitimate construct.
69 This will miss some errors, and is not a substitute for a code review.
70
erg@google.com35589e62010-11-17 18:58:16 +000071 To suppress false-positive errors of a certain category, add a
72 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
73 suppresses errors of all categories on that line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000074
75 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 +000076 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the
77 extensions with the --extensions flag.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000078
79 Flags:
80
81 output=vs7
82 By default, the output is formatted to ease emacs parsing. Visual Studio
83 compatible output (vs7) may also be used. Other formats are unsupported.
84
85 verbose=#
86 Specify a number 0-5 to restrict errors to certain verbosity levels.
87
88 filter=-x,+y,...
89 Specify a comma-separated list of category-filters to apply: only
90 error messages whose category names pass the filters will be printed.
91 (Category names are printed with the message and look like
92 "[whitespace/indent]".) Filters are evaluated left to right.
93 "-FOO" and "FOO" means "do not print categories that start with FOO".
94 "+FOO" means "do print categories that start with FOO".
95
96 Examples: --filter=-whitespace,+whitespace/braces
97 --filter=whitespace,runtime/printf,+runtime/printf_format
98 --filter=-,+build/include_what_you_use
99
100 To see a list of all the categories used in cpplint, pass no arg:
101 --filter=
erg@google.com26970fa2009-11-17 18:07:32 +0000102
103 counting=total|toplevel|detailed
104 The total number of errors found is always printed. If
105 'toplevel' is provided, then the count of errors in each of
106 the top-level categories like 'build' and 'whitespace' will
107 also be printed. If 'detailed' is provided, then a count
108 is provided for each category like 'build/class'.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000109
110 root=subdir
111 The root directory used for deriving header guard CPP variable.
112 By default, the header guard CPP variable is calculated as the relative
113 path to the directory that contains .git, .hg, or .svn. When this flag
114 is specified, the relative path is calculated from the specified
115 directory. If the specified directory does not exist, this flag is
116 ignored.
117
118 Examples:
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +0000119 Assuming that src/.git exists, the header guard CPP variables for
120 src/chrome/browser/ui/browser.h are:
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000121
122 No flag => CHROME_BROWSER_UI_BROWSER_H_
123 --root=chrome => BROWSER_UI_BROWSER_H_
124 --root=chrome/browser => UI_BROWSER_H_
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000125
126 linelength=digits
127 This is the allowed line length for the project. The default value is
128 80 characters.
129
130 Examples:
131 --linelength=120
132
133 extensions=extension,extension,...
134 The allowed file extensions that cpplint will check
135
136 Examples:
137 --extensions=hpp,cpp
avakulenko@google.com17449932014-07-28 22:13:33 +0000138
139 cpplint.py supports per-directory configurations specified in CPPLINT.cfg
140 files. CPPLINT.cfg file can contain a number of key=value pairs.
141 Currently the following options are supported:
142
143 set noparent
144 filter=+filter1,-filter2,...
145 exclude_files=regex
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000146 linelength=80
avakulenko@google.com17449932014-07-28 22:13:33 +0000147
148 "set noparent" option prevents cpplint from traversing directory tree
149 upwards looking for more .cfg files in parent directories. This option
150 is usually placed in the top-level project directory.
151
152 The "filter" option is similar in function to --filter flag. It specifies
153 message filters in addition to the |_DEFAULT_FILTERS| and those specified
154 through --filter command-line flag.
155
156 "exclude_files" allows to specify a regular expression to be matched against
157 a file name. If the expression matches, the file is skipped and not run
158 through liner.
159
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000160 "linelength" allows to specify the allowed line length for the project.
161
avakulenko@google.com17449932014-07-28 22:13:33 +0000162 CPPLINT.cfg has an effect on files in the same directory and all
163 sub-directories, unless overridden by a nested configuration file.
164
165 Example file:
166 filter=-build/include_order,+build/include_alpha
167 exclude_files=.*\.cc
168
169 The above example disables build/include_order warning and enables
170 build/include_alpha as well as excludes all .cc from being
171 processed by linter, in the current directory (where the .cfg
172 file is located) and all sub-directories.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000173"""
174
175# We categorize each error message we print. Here are the categories.
176# We want an explicit list so we can list them all in cpplint --filter=.
177# If you add a new error message with a new category, add it to the list
178# here! cpplint_unittest.py should tell you if you forget to do this.
erg@google.com35589e62010-11-17 18:58:16 +0000179_ERROR_CATEGORIES = [
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000180 'build/class',
181 'build/c++11',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000182 'build/c++14',
183 'build/c++tr1',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000184 'build/deprecated',
185 'build/endif_comment',
186 'build/explicit_make_pair',
187 'build/forward_decl',
188 'build/header_guard',
189 'build/include',
190 'build/include_alpha',
191 'build/include_order',
192 'build/include_what_you_use',
193 'build/namespaces',
194 'build/printf_format',
195 'build/storage_class',
196 'legal/copyright',
197 'readability/alt_tokens',
198 'readability/braces',
199 'readability/casting',
200 'readability/check',
201 'readability/constructors',
202 'readability/fn_size',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000203 'readability/inheritance',
204 'readability/multiline_comment',
205 'readability/multiline_string',
206 'readability/namespace',
207 'readability/nolint',
208 'readability/nul',
209 'readability/strings',
210 'readability/todo',
211 'readability/utf8',
212 'runtime/arrays',
213 'runtime/casting',
214 'runtime/explicit',
215 'runtime/int',
216 'runtime/init',
217 'runtime/invalid_increment',
218 'runtime/member_string_references',
219 'runtime/memset',
220 'runtime/indentation_namespace',
221 'runtime/operator',
222 'runtime/printf',
223 'runtime/printf_format',
224 'runtime/references',
225 'runtime/string',
226 'runtime/threadsafe_fn',
227 'runtime/vlog',
228 'whitespace/blank_line',
229 'whitespace/braces',
230 'whitespace/comma',
231 'whitespace/comments',
232 'whitespace/empty_conditional_body',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000233 'whitespace/empty_if_body',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000234 'whitespace/empty_loop_body',
235 'whitespace/end_of_line',
236 'whitespace/ending_newline',
237 'whitespace/forcolon',
238 'whitespace/indent',
239 'whitespace/line_length',
240 'whitespace/newline',
241 'whitespace/operators',
242 'whitespace/parens',
243 'whitespace/semicolon',
244 'whitespace/tab',
245 'whitespace/todo',
246 ]
247
248# These error categories are no longer enforced by cpplint, but for backwards-
249# compatibility they may still appear in NOLINT comments.
250_LEGACY_ERROR_CATEGORIES = [
251 'readability/streams',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000252 'readability/function',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000253 ]
erg@google.com6317a9c2009-06-25 00:28:19 +0000254
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000255# The default state of the category filter. This is overridden by the --filter=
erg@google.com6317a9c2009-06-25 00:28:19 +0000256# flag. By default all errors are on, so only add here categories that should be
257# off by default (i.e., categories that must be enabled by the --filter= flags).
258# All entries here should start with a '-' or '+', as in the --filter= flag.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000259_DEFAULT_FILTERS = ['-build/include_alpha']
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000260
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000261# The default list of categories suppressed for C (not C++) files.
262_DEFAULT_C_SUPPRESSED_CATEGORIES = [
263 'readability/casting',
264 ]
265
266# The default list of categories suppressed for Linux Kernel files.
267_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
268 'whitespace/tab',
269 ]
270
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000271# We used to check for high-bit characters, but after much discussion we
272# decided those were OK, as long as they were in UTF-8 and didn't represent
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000273# hard-coded international strings, which belong in a separate i18n file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000274
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000275# C++ headers
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000276_CPP_HEADERS = frozenset([
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000277 # Legacy
278 'algobase.h',
279 'algo.h',
280 'alloc.h',
281 'builtinbuf.h',
282 'bvector.h',
283 'complex.h',
284 'defalloc.h',
285 'deque.h',
286 'editbuf.h',
287 'fstream.h',
288 'function.h',
289 'hash_map',
290 'hash_map.h',
291 'hash_set',
292 'hash_set.h',
293 'hashtable.h',
294 'heap.h',
295 'indstream.h',
296 'iomanip.h',
297 'iostream.h',
298 'istream.h',
299 'iterator.h',
300 'list.h',
301 'map.h',
302 'multimap.h',
303 'multiset.h',
304 'ostream.h',
305 'pair.h',
306 'parsestream.h',
307 'pfstream.h',
308 'procbuf.h',
309 'pthread_alloc',
310 'pthread_alloc.h',
311 'rope',
312 'rope.h',
313 'ropeimpl.h',
314 'set.h',
315 'slist',
316 'slist.h',
317 'stack.h',
318 'stdiostream.h',
319 'stl_alloc.h',
320 'stl_relops.h',
321 'streambuf.h',
322 'stream.h',
323 'strfile.h',
324 'strstream.h',
325 'tempbuf.h',
326 'tree.h',
327 'type_traits.h',
328 'vector.h',
329 # 17.6.1.2 C++ library headers
330 'algorithm',
331 'array',
332 'atomic',
333 'bitset',
334 'chrono',
335 'codecvt',
336 'complex',
337 'condition_variable',
338 'deque',
339 'exception',
340 'forward_list',
341 'fstream',
342 'functional',
343 'future',
344 'initializer_list',
345 'iomanip',
346 'ios',
347 'iosfwd',
348 'iostream',
349 'istream',
350 'iterator',
351 'limits',
352 'list',
353 'locale',
354 'map',
355 'memory',
356 'mutex',
357 'new',
358 'numeric',
359 'ostream',
360 'queue',
361 'random',
362 'ratio',
363 'regex',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000364 'scoped_allocator',
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000365 'set',
366 'sstream',
367 'stack',
368 'stdexcept',
369 'streambuf',
370 'string',
371 'strstream',
372 'system_error',
373 'thread',
374 'tuple',
375 'typeindex',
376 'typeinfo',
377 'type_traits',
378 'unordered_map',
379 'unordered_set',
380 'utility',
381 'valarray',
382 'vector',
383 # 17.6.1.2 C++ headers for C library facilities
384 'cassert',
385 'ccomplex',
386 'cctype',
387 'cerrno',
388 'cfenv',
389 'cfloat',
390 'cinttypes',
391 'ciso646',
392 'climits',
393 'clocale',
394 'cmath',
395 'csetjmp',
396 'csignal',
397 'cstdalign',
398 'cstdarg',
399 'cstdbool',
400 'cstddef',
401 'cstdint',
402 'cstdio',
403 'cstdlib',
404 'cstring',
405 'ctgmath',
406 'ctime',
407 'cuchar',
408 'cwchar',
409 'cwctype',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000410 ])
411
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000412# Type names
413_TYPES = re.compile(
414 r'^(?:'
415 # [dcl.type.simple]
416 r'(char(16_t|32_t)?)|wchar_t|'
417 r'bool|short|int|long|signed|unsigned|float|double|'
418 # [support.types]
419 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
420 # [cstdint.syn]
421 r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
422 r'(u?int(max|ptr)_t)|'
423 r')$')
424
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000425
avakulenko@google.com59146752014-08-11 20:20:55 +0000426# These headers are excluded from [build/include] and [build/include_order]
427# checks:
428# - Anything not following google file name conventions (containing an
429# uppercase character, such as Python.h or nsStringAPI.h, for example).
430# - Lua headers.
431_THIRD_PARTY_HEADERS_PATTERN = re.compile(
432 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
433
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000434# Pattern for matching FileInfo.BaseName() against test file name
435_TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$'
436
437# Pattern that matches only complete whitespace, possibly across multiple lines.
438_EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL)
avakulenko@google.com59146752014-08-11 20:20:55 +0000439
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000440# Assertion macros. These are defined in base/logging.h and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000441# testing/base/public/gunit.h.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000442_CHECK_MACROS = [
erg@google.com6317a9c2009-06-25 00:28:19 +0000443 'DCHECK', 'CHECK',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000444 'EXPECT_TRUE', 'ASSERT_TRUE',
445 'EXPECT_FALSE', 'ASSERT_FALSE',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000446 ]
447
erg@google.com6317a9c2009-06-25 00:28:19 +0000448# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000449_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
450
451for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
452 ('>=', 'GE'), ('>', 'GT'),
453 ('<=', 'LE'), ('<', 'LT')]:
erg@google.com6317a9c2009-06-25 00:28:19 +0000454 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000455 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
456 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
457 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000458
459for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
460 ('>=', 'LT'), ('>', 'LE'),
461 ('<=', 'GT'), ('<', 'GE')]:
462 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
463 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000464
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000465# Alternative tokens and their replacements. For full list, see section 2.5
466# Alternative tokens [lex.digraph] in the C++ standard.
467#
468# Digraphs (such as '%:') are not included here since it's a mess to
469# match those on a word boundary.
470_ALT_TOKEN_REPLACEMENT = {
471 'and': '&&',
472 'bitor': '|',
473 'or': '||',
474 'xor': '^',
475 'compl': '~',
476 'bitand': '&',
477 'and_eq': '&=',
478 'or_eq': '|=',
479 'xor_eq': '^=',
480 'not': '!',
481 'not_eq': '!='
482 }
483
484# Compile regular expression that matches all the above keywords. The "[ =()]"
485# bit is meant to avoid matching these keywords outside of boolean expressions.
486#
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000487# False positives include C-style multi-line comments and multi-line strings
488# but those have always been troublesome for cpplint.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000489_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
490 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
491
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000492
493# These constants define types of headers for use with
494# _IncludeState.CheckNextIncludeOrder().
495_C_SYS_HEADER = 1
496_CPP_SYS_HEADER = 2
497_LIKELY_MY_HEADER = 3
498_POSSIBLE_MY_HEADER = 4
499_OTHER_HEADER = 5
500
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000501# These constants define the current inline assembly state
502_NO_ASM = 0 # Outside of inline assembly block
503_INSIDE_ASM = 1 # Inside inline assembly block
504_END_ASM = 2 # Last line of inline assembly block
505_BLOCK_ASM = 3 # The whole block is an inline assembly block
506
507# Match start of assembly blocks
508_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
509 r'(?:\s+(volatile|__volatile__))?'
510 r'\s*[{(]')
511
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000512# Match strings that indicate we're working on a C (not C++) file.
513_SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
514 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
515
516# Match string that indicates we're working on a Linux Kernel file.
517_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000518
519_regexp_compile_cache = {}
520
erg@google.com35589e62010-11-17 18:58:16 +0000521# {str, set(int)}: a map from error categories to sets of linenumbers
522# on which those errors are expected and should be suppressed.
523_error_suppressions = {}
524
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000525# The root directory used for deriving header guard CPP variable.
526# This is set by --root flag.
527_root = None
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +0000528
529# The project root directory. Used for deriving header guard CPP variable.
530# This is set by --project_root flag. Must be an absolute path.
531_project_root = None
sdefresne263e9282016-07-19 02:14:22 -0700532
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000533# The allowed line length of files.
534# This is set by --linelength flag.
535_line_length = 80
536
537# The allowed extensions for file names
538# This is set by --extensions flag.
539_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
540
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000541# {str, bool}: a map from error categories to booleans which indicate if the
542# category should be suppressed for every line.
543_global_error_suppressions = {}
544
545
erg@google.com35589e62010-11-17 18:58:16 +0000546def ParseNolintSuppressions(filename, raw_line, linenum, error):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000547 """Updates the global list of line error-suppressions.
erg@google.com35589e62010-11-17 18:58:16 +0000548
549 Parses any NOLINT comments on the current line, updating the global
550 error_suppressions store. Reports an error if the NOLINT comment
551 was malformed.
552
553 Args:
554 filename: str, the name of the input file.
555 raw_line: str, the line of input text, with comments.
556 linenum: int, the number of the current line.
557 error: function, an error handler.
558 """
avakulenko@google.com59146752014-08-11 20:20:55 +0000559 matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000560 if matched:
avakulenko@google.com59146752014-08-11 20:20:55 +0000561 if matched.group(1):
562 suppressed_line = linenum + 1
563 else:
564 suppressed_line = linenum
565 category = matched.group(2)
erg@google.com35589e62010-11-17 18:58:16 +0000566 if category in (None, '(*)'): # => "suppress all"
avakulenko@google.com59146752014-08-11 20:20:55 +0000567 _error_suppressions.setdefault(None, set()).add(suppressed_line)
erg@google.com35589e62010-11-17 18:58:16 +0000568 else:
569 if category.startswith('(') and category.endswith(')'):
570 category = category[1:-1]
571 if category in _ERROR_CATEGORIES:
avakulenko@google.com59146752014-08-11 20:20:55 +0000572 _error_suppressions.setdefault(category, set()).add(suppressed_line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000573 elif category not in _LEGACY_ERROR_CATEGORIES:
erg@google.com35589e62010-11-17 18:58:16 +0000574 error(filename, linenum, 'readability/nolint', 5,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000575 'Unknown NOLINT error category: %s' % category)
erg@google.com35589e62010-11-17 18:58:16 +0000576
577
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000578def ProcessGlobalSuppresions(lines):
579 """Updates the list of global error suppressions.
580
581 Parses any lint directives in the file that have global effect.
582
583 Args:
584 lines: An array of strings, each representing a line of the file, with the
585 last element being empty if the file is terminated with a newline.
586 """
587 for line in lines:
588 if _SEARCH_C_FILE.search(line):
589 for category in _DEFAULT_C_SUPPRESSED_CATEGORIES:
590 _global_error_suppressions[category] = True
591 if _SEARCH_KERNEL_FILE.search(line):
592 for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
593 _global_error_suppressions[category] = True
594
595
erg@google.com35589e62010-11-17 18:58:16 +0000596def ResetNolintSuppressions():
avakulenko@google.com59146752014-08-11 20:20:55 +0000597 """Resets the set of NOLINT suppressions to empty."""
erg@google.com35589e62010-11-17 18:58:16 +0000598 _error_suppressions.clear()
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000599 _global_error_suppressions.clear()
erg@google.com35589e62010-11-17 18:58:16 +0000600
601
602def IsErrorSuppressedByNolint(category, linenum):
603 """Returns true if the specified error category is suppressed on this line.
604
605 Consults the global error_suppressions map populated by
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000606 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
erg@google.com35589e62010-11-17 18:58:16 +0000607
608 Args:
609 category: str, the category of the error.
610 linenum: int, the current line number.
611 Returns:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000612 bool, True iff the error should be suppressed due to a NOLINT comment or
613 global suppression.
erg@google.com35589e62010-11-17 18:58:16 +0000614 """
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000615 return (_global_error_suppressions.get(category, False) or
616 linenum in _error_suppressions.get(category, set()) or
erg@google.com35589e62010-11-17 18:58:16 +0000617 linenum in _error_suppressions.get(None, set()))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000618
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000619
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000620def Match(pattern, s):
621 """Matches the string with the pattern, caching the compiled regexp."""
622 # The regexp compilation caching is inlined in both Match and Search for
623 # performance reasons; factoring it out into a separate function turns out
624 # to be noticeably expensive.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000625 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000626 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
627 return _regexp_compile_cache[pattern].match(s)
628
629
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000630def ReplaceAll(pattern, rep, s):
631 """Replaces instances of pattern in a string with a replacement.
632
633 The compiled regex is kept in a cache shared by Match and Search.
634
635 Args:
636 pattern: regex pattern
637 rep: replacement text
638 s: search string
639
640 Returns:
641 string with replacements made (or original string if no replacements)
642 """
643 if pattern not in _regexp_compile_cache:
644 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
645 return _regexp_compile_cache[pattern].sub(rep, s)
646
647
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000648def Search(pattern, s):
649 """Searches the string for the pattern, caching the compiled regexp."""
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000650 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000651 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
652 return _regexp_compile_cache[pattern].search(s)
653
654
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000655def _IsSourceExtension(s):
656 """File extension (excluding dot) matches a source file extension."""
657 return s in ('c', 'cc', 'cpp', 'cxx')
658
659
avakulenko@google.com59146752014-08-11 20:20:55 +0000660class _IncludeState(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000661 """Tracks line numbers for includes, and the order in which includes appear.
662
avakulenko@google.com59146752014-08-11 20:20:55 +0000663 include_list contains list of lists of (header, line number) pairs.
664 It's a lists of lists rather than just one flat list to make it
665 easier to update across preprocessor boundaries.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000666
667 Call CheckNextIncludeOrder() once for each header in the file, passing
668 in the type constants defined above. Calls in an illegal order will
669 raise an _IncludeError with an appropriate error message.
670
671 """
672 # self._section will move monotonically through this set. If it ever
673 # needs to move backwards, CheckNextIncludeOrder will raise an error.
674 _INITIAL_SECTION = 0
675 _MY_H_SECTION = 1
676 _C_SECTION = 2
677 _CPP_SECTION = 3
678 _OTHER_H_SECTION = 4
679
680 _TYPE_NAMES = {
681 _C_SYS_HEADER: 'C system header',
682 _CPP_SYS_HEADER: 'C++ system header',
683 _LIKELY_MY_HEADER: 'header this file implements',
684 _POSSIBLE_MY_HEADER: 'header this file may implement',
685 _OTHER_HEADER: 'other header',
686 }
687 _SECTION_NAMES = {
688 _INITIAL_SECTION: "... nothing. (This can't be an error.)",
689 _MY_H_SECTION: 'a header this file implements',
690 _C_SECTION: 'C system header',
691 _CPP_SECTION: 'C++ system header',
692 _OTHER_H_SECTION: 'other header',
693 }
694
695 def __init__(self):
avakulenko@google.com59146752014-08-11 20:20:55 +0000696 self.include_list = [[]]
697 self.ResetSection('')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000698
avakulenko@google.com59146752014-08-11 20:20:55 +0000699 def FindHeader(self, header):
700 """Check if a header has already been included.
701
702 Args:
703 header: header to check.
704 Returns:
705 Line number of previous occurrence, or -1 if the header has not
706 been seen before.
707 """
708 for section_list in self.include_list:
709 for f in section_list:
710 if f[0] == header:
711 return f[1]
712 return -1
713
714 def ResetSection(self, directive):
715 """Reset section checking for preprocessor directive.
716
717 Args:
718 directive: preprocessor directive (e.g. "if", "else").
719 """
erg@google.com26970fa2009-11-17 18:07:32 +0000720 # The name of the current section.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000721 self._section = self._INITIAL_SECTION
erg@google.com26970fa2009-11-17 18:07:32 +0000722 # The path of last found header.
723 self._last_header = ''
724
avakulenko@google.com59146752014-08-11 20:20:55 +0000725 # Update list of includes. Note that we never pop from the
726 # include list.
727 if directive in ('if', 'ifdef', 'ifndef'):
728 self.include_list.append([])
729 elif directive in ('else', 'elif'):
730 self.include_list[-1] = []
731
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000732 def SetLastHeader(self, header_path):
733 self._last_header = header_path
734
erg@google.com26970fa2009-11-17 18:07:32 +0000735 def CanonicalizeAlphabeticalOrder(self, header_path):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000736 """Returns a path canonicalized for alphabetical comparison.
erg@google.com26970fa2009-11-17 18:07:32 +0000737
738 - replaces "-" with "_" so they both cmp the same.
739 - removes '-inl' since we don't require them to be after the main header.
740 - lowercase everything, just in case.
741
742 Args:
743 header_path: Path to be canonicalized.
744
745 Returns:
746 Canonicalized path.
747 """
748 return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
749
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000750 def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
erg@google.com26970fa2009-11-17 18:07:32 +0000751 """Check if a header is in alphabetical order with the previous header.
752
753 Args:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000754 clean_lines: A CleansedLines instance containing the file.
755 linenum: The number of the line to check.
756 header_path: Canonicalized header to be checked.
erg@google.com26970fa2009-11-17 18:07:32 +0000757
758 Returns:
759 Returns true if the header is in alphabetical order.
760 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000761 # If previous section is different from current section, _last_header will
762 # be reset to empty string, so it's always less than current header.
763 #
764 # If previous line was a blank line, assume that the headers are
765 # intentionally sorted the way they are.
766 if (self._last_header > header_path and
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000767 Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
erg@google.com26970fa2009-11-17 18:07:32 +0000768 return False
erg@google.com26970fa2009-11-17 18:07:32 +0000769 return True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000770
771 def CheckNextIncludeOrder(self, header_type):
772 """Returns a non-empty error message if the next header is out of order.
773
774 This function also updates the internal state to be ready to check
775 the next include.
776
777 Args:
778 header_type: One of the _XXX_HEADER constants defined above.
779
780 Returns:
781 The empty string if the header is in the right order, or an
782 error message describing what's wrong.
783
784 """
785 error_message = ('Found %s after %s' %
786 (self._TYPE_NAMES[header_type],
787 self._SECTION_NAMES[self._section]))
788
erg@google.com26970fa2009-11-17 18:07:32 +0000789 last_section = self._section
790
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000791 if header_type == _C_SYS_HEADER:
792 if self._section <= self._C_SECTION:
793 self._section = self._C_SECTION
794 else:
erg@google.com26970fa2009-11-17 18:07:32 +0000795 self._last_header = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000796 return error_message
797 elif header_type == _CPP_SYS_HEADER:
798 if self._section <= self._CPP_SECTION:
799 self._section = self._CPP_SECTION
800 else:
erg@google.com26970fa2009-11-17 18:07:32 +0000801 self._last_header = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000802 return error_message
803 elif header_type == _LIKELY_MY_HEADER:
804 if self._section <= self._MY_H_SECTION:
805 self._section = self._MY_H_SECTION
806 else:
807 self._section = self._OTHER_H_SECTION
808 elif header_type == _POSSIBLE_MY_HEADER:
809 if self._section <= self._MY_H_SECTION:
810 self._section = self._MY_H_SECTION
811 else:
812 # This will always be the fallback because we're not sure
813 # enough that the header is associated with this file.
814 self._section = self._OTHER_H_SECTION
815 else:
816 assert header_type == _OTHER_HEADER
817 self._section = self._OTHER_H_SECTION
818
erg@google.com26970fa2009-11-17 18:07:32 +0000819 if last_section != self._section:
820 self._last_header = ''
821
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000822 return ''
823
824
825class _CppLintState(object):
826 """Maintains module-wide state.."""
827
828 def __init__(self):
829 self.verbose_level = 1 # global setting.
830 self.error_count = 0 # global count of reported errors
erg@google.com6317a9c2009-06-25 00:28:19 +0000831 # filters to apply when emitting error messages
832 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000833 # backup of filter list. Used to restore the state after each file.
834 self._filters_backup = self.filters[:]
erg@google.com26970fa2009-11-17 18:07:32 +0000835 self.counting = 'total' # In what way are we counting errors?
836 self.errors_by_category = {} # string to int dict storing error counts
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000837
838 # output format:
839 # "emacs" - format that emacs can parse (default)
840 # "vs7" - format that Microsoft Visual Studio 7 can parse
841 self.output_format = 'emacs'
842
843 def SetOutputFormat(self, output_format):
844 """Sets the output format for errors."""
845 self.output_format = output_format
846
847 def SetVerboseLevel(self, level):
848 """Sets the module's verbosity, and returns the previous setting."""
849 last_verbose_level = self.verbose_level
850 self.verbose_level = level
851 return last_verbose_level
852
erg@google.com26970fa2009-11-17 18:07:32 +0000853 def SetCountingStyle(self, counting_style):
854 """Sets the module's counting options."""
855 self.counting = counting_style
856
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000857 def SetFilters(self, filters):
858 """Sets the error-message filters.
859
860 These filters are applied when deciding whether to emit a given
861 error message.
862
863 Args:
864 filters: A string of comma-separated filters (eg "+whitespace/indent").
865 Each filter should start with + or -; else we die.
erg@google.com6317a9c2009-06-25 00:28:19 +0000866
867 Raises:
868 ValueError: The comma-separated filters did not all start with '+' or '-'.
869 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000870 """
erg@google.com6317a9c2009-06-25 00:28:19 +0000871 # Default filters always have less priority than the flag ones.
872 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000873 self.AddFilters(filters)
874
875 def AddFilters(self, filters):
876 """ Adds more filters to the existing list of error-message filters. """
erg@google.com6317a9c2009-06-25 00:28:19 +0000877 for filt in filters.split(','):
878 clean_filt = filt.strip()
879 if clean_filt:
880 self.filters.append(clean_filt)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000881 for filt in self.filters:
882 if not (filt.startswith('+') or filt.startswith('-')):
883 raise ValueError('Every filter in --filters must start with + or -'
884 ' (%s does not)' % filt)
885
avakulenko@google.com17449932014-07-28 22:13:33 +0000886 def BackupFilters(self):
887 """ Saves the current filter list to backup storage."""
888 self._filters_backup = self.filters[:]
889
890 def RestoreFilters(self):
891 """ Restores filters previously backed up."""
892 self.filters = self._filters_backup[:]
893
erg@google.com26970fa2009-11-17 18:07:32 +0000894 def ResetErrorCounts(self):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000895 """Sets the module's error statistic back to zero."""
896 self.error_count = 0
erg@google.com26970fa2009-11-17 18:07:32 +0000897 self.errors_by_category = {}
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000898
erg@google.com26970fa2009-11-17 18:07:32 +0000899 def IncrementErrorCount(self, category):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000900 """Bumps the module's error statistic."""
901 self.error_count += 1
erg@google.com26970fa2009-11-17 18:07:32 +0000902 if self.counting in ('toplevel', 'detailed'):
903 if self.counting != 'detailed':
904 category = category.split('/')[0]
905 if category not in self.errors_by_category:
906 self.errors_by_category[category] = 0
907 self.errors_by_category[category] += 1
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000908
erg@google.com26970fa2009-11-17 18:07:32 +0000909 def PrintErrorCounts(self):
910 """Print a summary of errors by category, and the total."""
911 for category, count in self.errors_by_category.iteritems():
912 sys.stderr.write('Category \'%s\' errors found: %d\n' %
913 (category, count))
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +0000914 sys.stderr.write('Total errors found: %d\n' % self.error_count)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000915
916_cpplint_state = _CppLintState()
917
918
919def _OutputFormat():
920 """Gets the module's output format."""
921 return _cpplint_state.output_format
922
923
924def _SetOutputFormat(output_format):
925 """Sets the module's output format."""
926 _cpplint_state.SetOutputFormat(output_format)
927
928
929def _VerboseLevel():
930 """Returns the module's verbosity setting."""
931 return _cpplint_state.verbose_level
932
933
934def _SetVerboseLevel(level):
935 """Sets the module's verbosity, and returns the previous setting."""
936 return _cpplint_state.SetVerboseLevel(level)
937
938
erg@google.com26970fa2009-11-17 18:07:32 +0000939def _SetCountingStyle(level):
940 """Sets the module's counting options."""
941 _cpplint_state.SetCountingStyle(level)
942
943
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000944def _Filters():
945 """Returns the module's list of output filters, as a list."""
946 return _cpplint_state.filters
947
948
949def _SetFilters(filters):
950 """Sets the module's error-message filters.
951
952 These filters are applied when deciding whether to emit a given
953 error message.
954
955 Args:
956 filters: A string of comma-separated filters (eg "whitespace/indent").
957 Each filter should start with + or -; else we die.
958 """
959 _cpplint_state.SetFilters(filters)
960
avakulenko@google.com17449932014-07-28 22:13:33 +0000961def _AddFilters(filters):
962 """Adds more filter overrides.
avakulenko@google.com59146752014-08-11 20:20:55 +0000963
avakulenko@google.com17449932014-07-28 22:13:33 +0000964 Unlike _SetFilters, this function does not reset the current list of filters
965 available.
966
967 Args:
968 filters: A string of comma-separated filters (eg "whitespace/indent").
969 Each filter should start with + or -; else we die.
970 """
971 _cpplint_state.AddFilters(filters)
972
973def _BackupFilters():
974 """ Saves the current filter list to backup storage."""
975 _cpplint_state.BackupFilters()
976
977def _RestoreFilters():
978 """ Restores filters previously backed up."""
979 _cpplint_state.RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000980
981class _FunctionState(object):
982 """Tracks current function name and the number of lines in its body."""
983
984 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
985 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
986
987 def __init__(self):
988 self.in_a_function = False
989 self.lines_in_function = 0
990 self.current_function = ''
991
992 def Begin(self, function_name):
993 """Start analyzing function body.
994
995 Args:
996 function_name: The name of the function being tracked.
997 """
998 self.in_a_function = True
999 self.lines_in_function = 0
1000 self.current_function = function_name
1001
1002 def Count(self):
1003 """Count line in current function body."""
1004 if self.in_a_function:
1005 self.lines_in_function += 1
1006
1007 def Check(self, error, filename, linenum):
1008 """Report if too many lines in function body.
1009
1010 Args:
1011 error: The function to call with any errors found.
1012 filename: The name of the current file.
1013 linenum: The number of the line to check.
1014 """
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001015 if not self.in_a_function:
1016 return
1017
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001018 if Match(r'T(EST|est)', self.current_function):
1019 base_trigger = self._TEST_TRIGGER
1020 else:
1021 base_trigger = self._NORMAL_TRIGGER
1022 trigger = base_trigger * 2**_VerboseLevel()
1023
1024 if self.lines_in_function > trigger:
1025 error_level = int(math.log(self.lines_in_function / base_trigger, 2))
1026 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
1027 if error_level > 5:
1028 error_level = 5
1029 error(filename, linenum, 'readability/fn_size', error_level,
1030 'Small and focused functions are preferred:'
1031 ' %s has %d non-comment lines'
1032 ' (error triggered by exceeding %d lines).' % (
1033 self.current_function, self.lines_in_function, trigger))
1034
1035 def End(self):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001036 """Stop analyzing function body."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001037 self.in_a_function = False
1038
1039
1040class _IncludeError(Exception):
1041 """Indicates a problem with the include order in a file."""
1042 pass
1043
1044
avakulenko@google.com59146752014-08-11 20:20:55 +00001045class FileInfo(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001046 """Provides utility functions for filenames.
1047
1048 FileInfo provides easy access to the components of a file's path
1049 relative to the project root.
1050 """
1051
1052 def __init__(self, filename):
1053 self._filename = filename
1054
1055 def FullName(self):
1056 """Make Windows paths like Unix."""
1057 return os.path.abspath(self._filename).replace('\\', '/')
1058
1059 def RepositoryName(self):
1060 """FullName after removing the local path to the repository.
1061
1062 If we have a real absolute path name here we can try to do something smart:
1063 detecting the root of the checkout and truncating /path/to/checkout from
1064 the name so that we get header guards that don't include things like
1065 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
1066 people on different computers who have checked the source out to different
1067 locations won't see bogus errors.
1068 """
1069 fullname = self.FullName()
1070
1071 if os.path.exists(fullname):
1072 project_dir = os.path.dirname(fullname)
1073
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00001074 if _project_root:
1075 prefix = os.path.commonprefix([_project_root, project_dir])
1076 return fullname[len(prefix) + 1:]
1077
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001078 if os.path.exists(os.path.join(project_dir, ".svn")):
1079 # If there's a .svn file in the current directory, we recursively look
1080 # up the directory tree for the top of the SVN checkout
1081 root_dir = project_dir
1082 one_up_dir = os.path.dirname(root_dir)
1083 while os.path.exists(os.path.join(one_up_dir, ".svn")):
1084 root_dir = os.path.dirname(root_dir)
1085 one_up_dir = os.path.dirname(one_up_dir)
1086
1087 prefix = os.path.commonprefix([root_dir, project_dir])
1088 return fullname[len(prefix) + 1:]
1089
erg@chromium.org7956a872011-11-30 01:44:03 +00001090 # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
1091 # searching up from the current path.
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00001092 root_dir = os.path.dirname(fullname)
1093 while (root_dir != os.path.dirname(root_dir) and
1094 not os.path.exists(os.path.join(root_dir, ".git")) and
1095 not os.path.exists(os.path.join(root_dir, ".hg")) and
1096 not os.path.exists(os.path.join(root_dir, ".svn"))):
1097 root_dir = os.path.dirname(root_dir)
erg@google.com35589e62010-11-17 18:58:16 +00001098
1099 if (os.path.exists(os.path.join(root_dir, ".git")) or
erg@chromium.org7956a872011-11-30 01:44:03 +00001100 os.path.exists(os.path.join(root_dir, ".hg")) or
1101 os.path.exists(os.path.join(root_dir, ".svn"))):
erg@google.com35589e62010-11-17 18:58:16 +00001102 prefix = os.path.commonprefix([root_dir, project_dir])
1103 return fullname[len(prefix) + 1:]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001104
1105 # Don't know what to do; header guard warnings may be wrong...
1106 return fullname
1107
1108 def Split(self):
1109 """Splits the file into the directory, basename, and extension.
1110
1111 For 'chrome/browser/browser.cc', Split() would
1112 return ('chrome/browser', 'browser', '.cc')
1113
1114 Returns:
1115 A tuple of (directory, basename, extension).
1116 """
1117
1118 googlename = self.RepositoryName()
1119 project, rest = os.path.split(googlename)
1120 return (project,) + os.path.splitext(rest)
1121
1122 def BaseName(self):
1123 """File base name - text after the final slash, before the final period."""
1124 return self.Split()[1]
1125
1126 def Extension(self):
1127 """File extension - text following the final period."""
1128 return self.Split()[2]
1129
1130 def NoExtension(self):
1131 """File has no source file extension."""
1132 return '/'.join(self.Split()[0:2])
1133
1134 def IsSource(self):
1135 """File has a source file extension."""
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001136 return _IsSourceExtension(self.Extension()[1:])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001137
1138
erg@google.com35589e62010-11-17 18:58:16 +00001139def _ShouldPrintError(category, confidence, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001140 """If confidence >= verbose, category passes filter and is not suppressed."""
erg@google.com35589e62010-11-17 18:58:16 +00001141
1142 # There are three ways we might decide not to print an error message:
1143 # a "NOLINT(category)" comment appears in the source,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001144 # the verbosity level isn't high enough, or the filters filter it out.
erg@google.com35589e62010-11-17 18:58:16 +00001145 if IsErrorSuppressedByNolint(category, linenum):
1146 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001147
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001148 if confidence < _cpplint_state.verbose_level:
1149 return False
1150
1151 is_filtered = False
1152 for one_filter in _Filters():
1153 if one_filter.startswith('-'):
1154 if category.startswith(one_filter[1:]):
1155 is_filtered = True
1156 elif one_filter.startswith('+'):
1157 if category.startswith(one_filter[1:]):
1158 is_filtered = False
1159 else:
1160 assert False # should have been checked for in SetFilter.
1161 if is_filtered:
1162 return False
1163
1164 return True
1165
1166
1167def Error(filename, linenum, category, confidence, message):
1168 """Logs the fact we've found a lint error.
1169
1170 We log where the error was found, and also our confidence in the error,
1171 that is, how certain we are this is a legitimate style regression, and
1172 not a misidentification or a use that's sometimes justified.
1173
erg@google.com35589e62010-11-17 18:58:16 +00001174 False positives can be suppressed by the use of
1175 "cpplint(category)" comments on the offending line. These are
1176 parsed into _error_suppressions.
1177
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001178 Args:
1179 filename: The name of the file containing the error.
1180 linenum: The number of the line containing the error.
1181 category: A string used to describe the "category" this bug
1182 falls under: "whitespace", say, or "runtime". Categories
1183 may have a hierarchy separated by slashes: "whitespace/indent".
1184 confidence: A number from 1-5 representing a confidence score for
1185 the error, with 5 meaning that we are certain of the problem,
1186 and 1 meaning that it could be a legitimate construct.
1187 message: The error message.
1188 """
erg@google.com35589e62010-11-17 18:58:16 +00001189 if _ShouldPrintError(category, confidence, linenum):
erg@google.com26970fa2009-11-17 18:07:32 +00001190 _cpplint_state.IncrementErrorCount(category)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001191 if _cpplint_state.output_format == 'vs7':
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00001192 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % (
1193 filename, linenum, message, category, confidence))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001194 elif _cpplint_state.output_format == 'eclipse':
1195 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % (
1196 filename, linenum, message, category, confidence))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001197 else:
1198 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % (
1199 filename, linenum, message, category, confidence))
1200
1201
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001202# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001203_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1204 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001205# Match a single C style comment on the same line.
1206_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
1207# Matches multi-line C style comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001208# This RE is a little bit more complicated than one might expect, because we
1209# have to take care of space removals tools so we can handle comments inside
1210# statements better.
1211# The current rule is: We only clear spaces from both sides when we're at the
1212# end of the line. Otherwise, we try to remove spaces from the right side,
1213# if this doesn't work we try on left side but only if there's a non-character
1214# on the right.
1215_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001216 r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
1217 _RE_PATTERN_C_COMMENTS + r'\s+|' +
1218 r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
1219 _RE_PATTERN_C_COMMENTS + r')')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001220
1221
1222def IsCppString(line):
1223 """Does line terminate so, that the next symbol is in string constant.
1224
1225 This function does not consider single-line nor multi-line comments.
1226
1227 Args:
1228 line: is a partial line of code starting from the 0..n.
1229
1230 Returns:
1231 True, if next character appended to 'line' is inside a
1232 string constant.
1233 """
1234
1235 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
1236 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
1237
1238
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001239def CleanseRawStrings(raw_lines):
1240 """Removes C++11 raw strings from lines.
1241
1242 Before:
1243 static const char kData[] = R"(
1244 multi-line string
1245 )";
1246
1247 After:
1248 static const char kData[] = ""
1249 (replaced by blank line)
1250 "";
1251
1252 Args:
1253 raw_lines: list of raw lines.
1254
1255 Returns:
1256 list of lines with C++11 raw strings replaced by empty strings.
1257 """
1258
1259 delimiter = None
1260 lines_without_raw_strings = []
1261 for line in raw_lines:
1262 if delimiter:
1263 # Inside a raw string, look for the end
1264 end = line.find(delimiter)
1265 if end >= 0:
1266 # Found the end of the string, match leading space for this
1267 # line and resume copying the original lines, and also insert
1268 # a "" on the last line.
1269 leading_space = Match(r'^(\s*)\S', line)
1270 line = leading_space.group(1) + '""' + line[end + len(delimiter):]
1271 delimiter = None
1272 else:
1273 # Haven't found the end yet, append a blank line.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001274 line = '""'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001275
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001276 # Look for beginning of a raw string, and replace them with
1277 # empty strings. This is done in a loop to handle multiple raw
1278 # strings on the same line.
1279 while delimiter is None:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001280 # Look for beginning of a raw string.
1281 # See 2.14.15 [lex.string] for syntax.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001282 #
1283 # Once we have matched a raw string, we check the prefix of the
1284 # line to make sure that the line is not part of a single line
1285 # comment. It's done this way because we remove raw strings
1286 # before removing comments as opposed to removing comments
1287 # before removing raw strings. This is because there are some
1288 # cpplint checks that requires the comments to be preserved, but
1289 # we don't want to check comments that are inside raw strings.
1290 matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1291 if (matched and
1292 not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
1293 matched.group(1))):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001294 delimiter = ')' + matched.group(2) + '"'
1295
1296 end = matched.group(3).find(delimiter)
1297 if end >= 0:
1298 # Raw string ended on same line
1299 line = (matched.group(1) + '""' +
1300 matched.group(3)[end + len(delimiter):])
1301 delimiter = None
1302 else:
1303 # Start of a multi-line raw string
1304 line = matched.group(1) + '""'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001305 else:
1306 break
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001307
1308 lines_without_raw_strings.append(line)
1309
1310 # TODO(unknown): if delimiter is not None here, we might want to
1311 # emit a warning for unterminated string.
1312 return lines_without_raw_strings
1313
1314
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001315def FindNextMultiLineCommentStart(lines, lineix):
1316 """Find the beginning marker for a multiline comment."""
1317 while lineix < len(lines):
1318 if lines[lineix].strip().startswith('/*'):
1319 # Only return this marker if the comment goes beyond this line
1320 if lines[lineix].strip().find('*/', 2) < 0:
1321 return lineix
1322 lineix += 1
1323 return len(lines)
1324
1325
1326def FindNextMultiLineCommentEnd(lines, lineix):
1327 """We are inside a comment, find the end marker."""
1328 while lineix < len(lines):
1329 if lines[lineix].strip().endswith('*/'):
1330 return lineix
1331 lineix += 1
1332 return len(lines)
1333
1334
1335def RemoveMultiLineCommentsFromRange(lines, begin, end):
1336 """Clears a range of lines for multi-line comments."""
1337 # Having // dummy comments makes the lines non-empty, so we will not get
1338 # unnecessary blank line warnings later in the code.
1339 for i in range(begin, end):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001340 lines[i] = '/**/'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001341
1342
1343def RemoveMultiLineComments(filename, lines, error):
1344 """Removes multiline (c-style) comments from lines."""
1345 lineix = 0
1346 while lineix < len(lines):
1347 lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
1348 if lineix_begin >= len(lines):
1349 return
1350 lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
1351 if lineix_end >= len(lines):
1352 error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
1353 'Could not find end of multi-line comment')
1354 return
1355 RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
1356 lineix = lineix_end + 1
1357
1358
1359def CleanseComments(line):
1360 """Removes //-comments and single-line C-style /* */ comments.
1361
1362 Args:
1363 line: A line of C++ source.
1364
1365 Returns:
1366 The line with single-line comments removed.
1367 """
1368 commentpos = line.find('//')
1369 if commentpos != -1 and not IsCppString(line[:commentpos]):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001370 line = line[:commentpos].rstrip()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001371 # get rid of /* ... */
1372 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
1373
1374
erg@google.com6317a9c2009-06-25 00:28:19 +00001375class CleansedLines(object):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001376 """Holds 4 copies of all lines with different preprocessing applied to them.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001377
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001378 1) elided member contains lines without strings and comments.
1379 2) lines member contains lines without comments.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001380 3) raw_lines member contains all the lines without processing.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001381 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
1382 strings removed.
1383 All these members are of <type 'list'>, and of the same length.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001384 """
1385
1386 def __init__(self, lines):
1387 self.elided = []
1388 self.lines = []
1389 self.raw_lines = lines
1390 self.num_lines = len(lines)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001391 self.lines_without_raw_strings = CleanseRawStrings(lines)
1392 for linenum in range(len(self.lines_without_raw_strings)):
1393 self.lines.append(CleanseComments(
1394 self.lines_without_raw_strings[linenum]))
1395 elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001396 self.elided.append(CleanseComments(elided))
1397
1398 def NumLines(self):
1399 """Returns the number of lines represented."""
1400 return self.num_lines
1401
1402 @staticmethod
1403 def _CollapseStrings(elided):
1404 """Collapses strings and chars on a line to simple "" or '' blocks.
1405
1406 We nix strings first so we're not fooled by text like '"http://"'
1407
1408 Args:
1409 elided: The line being processed.
1410
1411 Returns:
1412 The line with collapsed strings.
1413 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001414 if _RE_PATTERN_INCLUDE.match(elided):
1415 return elided
1416
1417 # Remove escaped characters first to make quote/single quote collapsing
1418 # basic. Things that look like escaped characters shouldn't occur
1419 # outside of strings and chars.
1420 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
1421
1422 # Replace quoted strings and digit separators. Both single quotes
1423 # and double quotes are processed in the same loop, otherwise
1424 # nested quotes wouldn't work.
1425 collapsed = ''
1426 while True:
1427 # Find the first quote character
1428 match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
1429 if not match:
1430 collapsed += elided
1431 break
1432 head, quote, tail = match.groups()
1433
1434 if quote == '"':
1435 # Collapse double quoted strings
1436 second_quote = tail.find('"')
1437 if second_quote >= 0:
1438 collapsed += head + '""'
1439 elided = tail[second_quote + 1:]
1440 else:
1441 # Unmatched double quote, don't bother processing the rest
1442 # of the line since this is probably a multiline string.
1443 collapsed += elided
1444 break
1445 else:
1446 # Found single quote, check nearby text to eliminate digit separators.
1447 #
1448 # There is no special handling for floating point here, because
1449 # the integer/fractional/exponent parts would all be parsed
1450 # correctly as long as there are digits on both sides of the
1451 # separator. So we are fine as long as we don't see something
1452 # like "0.'3" (gcc 4.9.0 will not allow this literal).
1453 if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1454 match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
1455 collapsed += head + match_literal.group(1).replace("'", '')
1456 elided = match_literal.group(2)
1457 else:
1458 second_quote = tail.find('\'')
1459 if second_quote >= 0:
1460 collapsed += head + "''"
1461 elided = tail[second_quote + 1:]
1462 else:
1463 # Unmatched single quote
1464 collapsed += elided
1465 break
1466
1467 return collapsed
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001468
1469
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001470def FindEndOfExpressionInLine(line, startpos, stack):
1471 """Find the position just after the end of current parenthesized expression.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001472
1473 Args:
1474 line: a CleansedLines line.
1475 startpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001476 stack: nesting stack at startpos.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001477
1478 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001479 On finding matching end: (index just after matching end, None)
1480 On finding an unclosed expression: (-1, None)
1481 Otherwise: (-1, new stack at end of this line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001482 """
1483 for i in xrange(startpos, len(line)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001484 char = line[i]
1485 if char in '([{':
1486 # Found start of parenthesized expression, push to expression stack
1487 stack.append(char)
1488 elif char == '<':
1489 # Found potential start of template argument list
1490 if i > 0 and line[i - 1] == '<':
1491 # Left shift operator
1492 if stack and stack[-1] == '<':
1493 stack.pop()
1494 if not stack:
1495 return (-1, None)
1496 elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
1497 # operator<, don't add to stack
1498 continue
1499 else:
1500 # Tentative start of template argument list
1501 stack.append('<')
1502 elif char in ')]}':
1503 # Found end of parenthesized expression.
1504 #
1505 # If we are currently expecting a matching '>', the pending '<'
1506 # must have been an operator. Remove them from expression stack.
1507 while stack and stack[-1] == '<':
1508 stack.pop()
1509 if not stack:
1510 return (-1, None)
1511 if ((stack[-1] == '(' and char == ')') or
1512 (stack[-1] == '[' and char == ']') or
1513 (stack[-1] == '{' and char == '}')):
1514 stack.pop()
1515 if not stack:
1516 return (i + 1, None)
1517 else:
1518 # Mismatched parentheses
1519 return (-1, None)
1520 elif char == '>':
1521 # Found potential end of template argument list.
1522
1523 # Ignore "->" and operator functions
1524 if (i > 0 and
1525 (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
1526 continue
1527
1528 # Pop the stack if there is a matching '<'. Otherwise, ignore
1529 # this '>' since it must be an operator.
1530 if stack:
1531 if stack[-1] == '<':
1532 stack.pop()
1533 if not stack:
1534 return (i + 1, None)
1535 elif char == ';':
1536 # Found something that look like end of statements. If we are currently
1537 # expecting a '>', the matching '<' must have been an operator, since
1538 # template argument list should not contain statements.
1539 while stack and stack[-1] == '<':
1540 stack.pop()
1541 if not stack:
1542 return (-1, None)
1543
1544 # Did not find end of expression or unbalanced parentheses on this line
1545 return (-1, stack)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001546
1547
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001548def CloseExpression(clean_lines, linenum, pos):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001549 """If input points to ( or { or [ or <, finds the position that closes it.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001550
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001551 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001552 linenum/pos that correspond to the closing of the expression.
1553
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001554 TODO(unknown): cpplint spends a fair bit of time matching parentheses.
1555 Ideally we would want to index all opening and closing parentheses once
1556 and have CloseExpression be just a simple lookup, but due to preprocessor
1557 tricks, this is not so easy.
1558
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001559 Args:
1560 clean_lines: A CleansedLines instance containing the file.
1561 linenum: The number of the line to check.
1562 pos: A position on the line.
1563
1564 Returns:
1565 A tuple (line, linenum, pos) pointer *past* the closing brace, or
1566 (line, len(lines), -1) if we never find a close. Note we ignore
1567 strings and comments when matching; and the line we return is the
1568 'cleansed' line at linenum.
1569 """
1570
1571 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001572 if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001573 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001574
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001575 # Check first line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001576 (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001577 if end_pos > -1:
1578 return (line, linenum, end_pos)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001579
1580 # Continue scanning forward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001581 while stack and linenum < clean_lines.NumLines() - 1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001582 linenum += 1
1583 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001584 (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001585 if end_pos > -1:
1586 return (line, linenum, end_pos)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001587
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001588 # Did not find end of expression before end of file, give up
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001589 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001590
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001591
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001592def FindStartOfExpressionInLine(line, endpos, stack):
1593 """Find position at the matching start of current expression.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001594
1595 This is almost the reverse of FindEndOfExpressionInLine, but note
1596 that the input position and returned position differs by 1.
1597
1598 Args:
1599 line: a CleansedLines line.
1600 endpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001601 stack: nesting stack at endpos.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001602
1603 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001604 On finding matching start: (index at matching start, None)
1605 On finding an unclosed expression: (-1, None)
1606 Otherwise: (-1, new stack at beginning of this line)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001607 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001608 i = endpos
1609 while i >= 0:
1610 char = line[i]
1611 if char in ')]}':
1612 # Found end of expression, push to expression stack
1613 stack.append(char)
1614 elif char == '>':
1615 # Found potential end of template argument list.
1616 #
1617 # Ignore it if it's a "->" or ">=" or "operator>"
1618 if (i > 0 and
1619 (line[i - 1] == '-' or
1620 Match(r'\s>=\s', line[i - 1:]) or
1621 Search(r'\boperator\s*$', line[0:i]))):
1622 i -= 1
1623 else:
1624 stack.append('>')
1625 elif char == '<':
1626 # Found potential start of template argument list
1627 if i > 0 and line[i - 1] == '<':
1628 # Left shift operator
1629 i -= 1
1630 else:
1631 # If there is a matching '>', we can pop the expression stack.
1632 # Otherwise, ignore this '<' since it must be an operator.
1633 if stack and stack[-1] == '>':
1634 stack.pop()
1635 if not stack:
1636 return (i, None)
1637 elif char in '([{':
1638 # Found start of expression.
1639 #
1640 # If there are any unmatched '>' on the stack, they must be
1641 # operators. Remove those.
1642 while stack and stack[-1] == '>':
1643 stack.pop()
1644 if not stack:
1645 return (-1, None)
1646 if ((char == '(' and stack[-1] == ')') or
1647 (char == '[' and stack[-1] == ']') or
1648 (char == '{' and stack[-1] == '}')):
1649 stack.pop()
1650 if not stack:
1651 return (i, None)
1652 else:
1653 # Mismatched parentheses
1654 return (-1, None)
1655 elif char == ';':
1656 # Found something that look like end of statements. If we are currently
1657 # expecting a '<', the matching '>' must have been an operator, since
1658 # template argument list should not contain statements.
1659 while stack and stack[-1] == '>':
1660 stack.pop()
1661 if not stack:
1662 return (-1, None)
1663
1664 i -= 1
1665
1666 return (-1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001667
1668
1669def ReverseCloseExpression(clean_lines, linenum, pos):
1670 """If input points to ) or } or ] or >, finds the position that opens it.
1671
1672 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1673 linenum/pos that correspond to the opening of the expression.
1674
1675 Args:
1676 clean_lines: A CleansedLines instance containing the file.
1677 linenum: The number of the line to check.
1678 pos: A position on the line.
1679
1680 Returns:
1681 A tuple (line, linenum, pos) pointer *at* the opening brace, or
1682 (line, 0, -1) if we never find the matching opening brace. Note
1683 we ignore strings and comments when matching; and the line we
1684 return is the 'cleansed' line at linenum.
1685 """
1686 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001687 if line[pos] not in ')}]>':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001688 return (line, 0, -1)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001689
1690 # Check last line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001691 (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001692 if start_pos > -1:
1693 return (line, linenum, start_pos)
1694
1695 # Continue scanning backward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001696 while stack and linenum > 0:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001697 linenum -= 1
1698 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001699 (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001700 if start_pos > -1:
1701 return (line, linenum, start_pos)
1702
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001703 # Did not find start of expression before beginning of file, give up
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001704 return (line, 0, -1)
1705
1706
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001707def CheckForCopyright(filename, lines, error):
1708 """Logs an error if no Copyright message appears at the top of the file."""
1709
1710 # We'll say it should occur by line 10. Don't forget there's a
1711 # dummy line at the front.
1712 for line in xrange(1, min(len(lines), 11)):
1713 if re.search(r'Copyright', lines[line], re.I): break
1714 else: # means no copyright line was found
1715 error(filename, 0, 'legal/copyright', 5,
1716 'No copyright message found. '
1717 'You should have a line: "Copyright [year] <Copyright Owner>"')
1718
1719
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001720def GetIndentLevel(line):
1721 """Return the number of leading spaces in line.
1722
1723 Args:
1724 line: A string to check.
1725
1726 Returns:
1727 An integer count of leading spaces, possibly zero.
1728 """
1729 indent = Match(r'^( *)\S', line)
1730 if indent:
1731 return len(indent.group(1))
1732 else:
1733 return 0
1734
1735
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001736def GetHeaderGuardCPPVariable(filename):
1737 """Returns the CPP variable that should be used as a header guard.
1738
1739 Args:
1740 filename: The name of a C++ header file.
1741
1742 Returns:
1743 The CPP variable that should be used as a header guard in the
1744 named file.
1745
1746 """
1747
erg@google.com35589e62010-11-17 18:58:16 +00001748 # Restores original filename in case that cpplint is invoked from Emacs's
1749 # flymake.
1750 filename = re.sub(r'_flymake\.h$', '.h', filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001751 filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001752 # Replace 'c++' with 'cpp'.
1753 filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
skym@chromium.org3990c412016-02-05 20:55:12 +00001754
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001755 fileinfo = FileInfo(filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001756 file_path_from_root = fileinfo.RepositoryName()
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00001757 if _root:
1758 file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001759 return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001760
1761
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001762def CheckForHeaderGuard(filename, clean_lines, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001763 """Checks that the file contains a header guard.
1764
erg@google.com6317a9c2009-06-25 00:28:19 +00001765 Logs an error if no #ifndef header guard is present. For other
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001766 headers, checks that the full pathname is used.
1767
1768 Args:
1769 filename: The name of the C++ header file.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001770 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001771 error: The function to call with any errors found.
1772 """
1773
avakulenko@google.com59146752014-08-11 20:20:55 +00001774 # Don't check for header guards if there are error suppression
1775 # comments somewhere in this file.
1776 #
1777 # Because this is silencing a warning for a nonexistent line, we
1778 # only support the very specific NOLINT(build/header_guard) syntax,
1779 # and not the general NOLINT or NOLINT(*) syntax.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001780 raw_lines = clean_lines.lines_without_raw_strings
1781 for i in raw_lines:
avakulenko@google.com59146752014-08-11 20:20:55 +00001782 if Search(r'//\s*NOLINT\(build/header_guard\)', i):
1783 return
1784
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001785 cppvar = GetHeaderGuardCPPVariable(filename)
1786
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001787 ifndef = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001788 ifndef_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001789 define = ''
1790 endif = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001791 endif_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001792 for linenum, line in enumerate(raw_lines):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001793 linesplit = line.split()
1794 if len(linesplit) >= 2:
1795 # find the first occurrence of #ifndef and #define, save arg
1796 if not ifndef and linesplit[0] == '#ifndef':
1797 # set ifndef to the header guard presented on the #ifndef line.
1798 ifndef = linesplit[1]
1799 ifndef_linenum = linenum
1800 if not define and linesplit[0] == '#define':
1801 define = linesplit[1]
1802 # find the last occurrence of #endif, save entire line
1803 if line.startswith('#endif'):
1804 endif = line
1805 endif_linenum = linenum
1806
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001807 if not ifndef or not define or ifndef != define:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001808 error(filename, 0, 'build/header_guard', 5,
1809 'No #ifndef header guard found, suggested CPP variable is: %s' %
1810 cppvar)
1811 return
1812
1813 # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
1814 # for backward compatibility.
erg@google.com35589e62010-11-17 18:58:16 +00001815 if ifndef != cppvar:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001816 error_level = 0
1817 if ifndef != cppvar + '_':
1818 error_level = 5
1819
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001820 ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
erg@google.com35589e62010-11-17 18:58:16 +00001821 error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001822 error(filename, ifndef_linenum, 'build/header_guard', error_level,
1823 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1824
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001825 # Check for "//" comments on endif line.
1826 ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
1827 error)
1828 match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
1829 if match:
1830 if match.group(1) == '_':
1831 # Issue low severity warning for deprecated double trailing underscore
1832 error(filename, endif_linenum, 'build/header_guard', 0,
1833 '#endif line should be "#endif // %s"' % cppvar)
erg@chromium.orgc452fea2012-01-26 21:10:45 +00001834 return
1835
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001836 # Didn't find the corresponding "//" comment. If this file does not
1837 # contain any "//" comments at all, it could be that the compiler
1838 # only wants "/**/" comments, look for those instead.
1839 no_single_line_comments = True
1840 for i in xrange(1, len(raw_lines) - 1):
1841 line = raw_lines[i]
1842 if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
1843 no_single_line_comments = False
1844 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001845
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001846 if no_single_line_comments:
1847 match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
1848 if match:
1849 if match.group(1) == '_':
1850 # Low severity warning for double trailing underscore
1851 error(filename, endif_linenum, 'build/header_guard', 0,
1852 '#endif line should be "#endif /* %s */"' % cppvar)
1853 return
1854
1855 # Didn't find anything
1856 error(filename, endif_linenum, 'build/header_guard', 5,
1857 '#endif line should be "#endif // %s"' % cppvar)
1858
1859
1860def CheckHeaderFileIncluded(filename, include_state, error):
1861 """Logs an error if a .cc file does not include its header."""
1862
1863 # Do not check test files
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001864 fileinfo = FileInfo(filename)
1865 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001866 return
1867
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001868 headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h'
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001869 if not os.path.exists(headerfile):
1870 return
1871 headername = FileInfo(headerfile).RepositoryName()
1872 first_include = 0
1873 for section_list in include_state.include_list:
1874 for f in section_list:
1875 if headername in f[0] or f[0] in headername:
1876 return
1877 if not first_include:
1878 first_include = f[1]
1879
1880 error(filename, first_include, 'build/include', 5,
1881 '%s should include its header file %s' % (fileinfo.RepositoryName(),
1882 headername))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001883
1884
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001885def CheckForBadCharacters(filename, lines, error):
1886 """Logs an error for each line containing bad characters.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001887
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001888 Two kinds of bad characters:
1889
1890 1. Unicode replacement characters: These indicate that either the file
1891 contained invalid UTF-8 (likely) or Unicode replacement characters (which
1892 it shouldn't). Note that it's possible for this to throw off line
1893 numbering if the invalid UTF-8 occurred adjacent to a newline.
1894
1895 2. NUL bytes. These are problematic for some tools.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001896
1897 Args:
1898 filename: The name of the current file.
1899 lines: An array of strings, each representing a line of the file.
1900 error: The function to call with any errors found.
1901 """
1902 for linenum, line in enumerate(lines):
1903 if u'\ufffd' in line:
1904 error(filename, linenum, 'readability/utf8', 5,
1905 'Line contains invalid UTF-8 (or Unicode replacement character).')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001906 if '\0' in line:
1907 error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001908
1909
1910def CheckForNewlineAtEOF(filename, lines, error):
1911 """Logs an error if there is no newline char at the end of the file.
1912
1913 Args:
1914 filename: The name of the current file.
1915 lines: An array of strings, each representing a line of the file.
1916 error: The function to call with any errors found.
1917 """
1918
1919 # The array lines() was created by adding two newlines to the
1920 # original file (go figure), then splitting on \n.
1921 # To verify that the file ends in \n, we just have to make sure the
1922 # last-but-two element of lines() exists and is empty.
1923 if len(lines) < 3 or lines[-2]:
1924 error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
1925 'Could not find a newline character at the end of the file.')
1926
1927
1928def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
1929 """Logs an error if we see /* ... */ or "..." that extend past one line.
1930
1931 /* ... */ comments are legit inside macros, for one line.
1932 Otherwise, we prefer // comments, so it's ok to warn about the
1933 other. Likewise, it's ok for strings to extend across multiple
1934 lines, as long as a line continuation character (backslash)
1935 terminates each line. Although not currently prohibited by the C++
1936 style guide, it's ugly and unnecessary. We don't do well with either
1937 in this lint program, so we warn about both.
1938
1939 Args:
1940 filename: The name of the current file.
1941 clean_lines: A CleansedLines instance containing the file.
1942 linenum: The number of the line to check.
1943 error: The function to call with any errors found.
1944 """
1945 line = clean_lines.elided[linenum]
1946
1947 # Remove all \\ (escaped backslashes) from the line. They are OK, and the
1948 # second (escaped) slash may trigger later \" detection erroneously.
1949 line = line.replace('\\\\', '')
1950
1951 if line.count('/*') > line.count('*/'):
1952 error(filename, linenum, 'readability/multiline_comment', 5,
1953 'Complex multi-line /*...*/-style comment found. '
1954 'Lint may give bogus warnings. '
1955 'Consider replacing these with //-style comments, '
1956 'with #if 0...#endif, '
1957 'or with more clearly structured multi-line comments.')
1958
1959 if (line.count('"') - line.count('\\"')) % 2:
1960 error(filename, linenum, 'readability/multiline_string', 5,
1961 'Multi-line string ("...") found. This lint script doesn\'t '
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001962 'do well with such strings, and may give bogus warnings. '
1963 'Use C++11 raw strings or concatenation instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001964
1965
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001966# (non-threadsafe name, thread-safe alternative, validation pattern)
1967#
1968# The validation pattern is used to eliminate false positives such as:
1969# _rand(); // false positive due to substring match.
1970# ->rand(); // some member function rand().
1971# ACMRandom rand(seed); // some variable named rand.
1972# ISAACRandom rand(); // another variable named rand.
1973#
1974# Basically we require the return value of these functions to be used
1975# in some expression context on the same line by matching on some
1976# operator before the function name. This eliminates constructors and
1977# member function calls.
1978_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
1979_THREADING_LIST = (
1980 ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
1981 ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
1982 ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
1983 ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
1984 ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
1985 ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
1986 ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
1987 ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
1988 ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
1989 ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
1990 ('strtok(', 'strtok_r(',
1991 _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
1992 ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001993 )
1994
1995
1996def CheckPosixThreading(filename, clean_lines, linenum, error):
1997 """Checks for calls to thread-unsafe functions.
1998
1999 Much code has been originally written without consideration of
2000 multi-threading. Also, engineers are relying on their old experience;
2001 they have learned posix before threading extensions were added. These
2002 tests guide the engineers to use thread-safe functions (when using
2003 posix directly).
2004
2005 Args:
2006 filename: The name of the current file.
2007 clean_lines: A CleansedLines instance containing the file.
2008 linenum: The number of the line to check.
2009 error: The function to call with any errors found.
2010 """
2011 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002012 for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
2013 # Additional pattern matching check to confirm that this is the
2014 # function we are looking for
2015 if Search(pattern, line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002016 error(filename, linenum, 'runtime/threadsafe_fn', 2,
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002017 'Consider using ' + multithread_safe_func +
2018 '...) instead of ' + single_thread_func +
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002019 '...) for improved thread safety.')
2020
2021
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002022def CheckVlogArguments(filename, clean_lines, linenum, error):
2023 """Checks that VLOG() is only used for defining a logging level.
2024
2025 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
2026 VLOG(FATAL) are not.
2027
2028 Args:
2029 filename: The name of the current file.
2030 clean_lines: A CleansedLines instance containing the file.
2031 linenum: The number of the line to check.
2032 error: The function to call with any errors found.
2033 """
2034 line = clean_lines.elided[linenum]
2035 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
2036 error(filename, linenum, 'runtime/vlog', 5,
2037 'VLOG() should be used with numeric verbosity level. '
2038 'Use LOG() if you want symbolic severity levels.')
2039
erg@google.com26970fa2009-11-17 18:07:32 +00002040# Matches invalid increment: *count++, which moves pointer instead of
erg@google.com6317a9c2009-06-25 00:28:19 +00002041# incrementing a value.
erg@google.com26970fa2009-11-17 18:07:32 +00002042_RE_PATTERN_INVALID_INCREMENT = re.compile(
erg@google.com6317a9c2009-06-25 00:28:19 +00002043 r'^\s*\*\w+(\+\+|--);')
2044
2045
2046def CheckInvalidIncrement(filename, clean_lines, linenum, error):
erg@google.com26970fa2009-11-17 18:07:32 +00002047 """Checks for invalid increment *count++.
erg@google.com6317a9c2009-06-25 00:28:19 +00002048
2049 For example following function:
2050 void increment_counter(int* count) {
2051 *count++;
2052 }
2053 is invalid, because it effectively does count++, moving pointer, and should
2054 be replaced with ++*count, (*count)++ or *count += 1.
2055
2056 Args:
2057 filename: The name of the current file.
2058 clean_lines: A CleansedLines instance containing the file.
2059 linenum: The number of the line to check.
2060 error: The function to call with any errors found.
2061 """
2062 line = clean_lines.elided[linenum]
erg@google.com26970fa2009-11-17 18:07:32 +00002063 if _RE_PATTERN_INVALID_INCREMENT.match(line):
erg@google.com6317a9c2009-06-25 00:28:19 +00002064 error(filename, linenum, 'runtime/invalid_increment', 5,
2065 'Changing pointer instead of value (or unused value of operator*).')
2066
2067
avakulenko@google.com59146752014-08-11 20:20:55 +00002068def IsMacroDefinition(clean_lines, linenum):
2069 if Search(r'^#define', clean_lines[linenum]):
2070 return True
2071
2072 if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
2073 return True
2074
2075 return False
2076
2077
2078def IsForwardClassDeclaration(clean_lines, linenum):
2079 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
2080
2081
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002082class _BlockInfo(object):
2083 """Stores information about a generic block of code."""
2084
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002085 def __init__(self, linenum, seen_open_brace):
2086 self.starting_linenum = linenum
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002087 self.seen_open_brace = seen_open_brace
2088 self.open_parentheses = 0
2089 self.inline_asm = _NO_ASM
avakulenko@google.com59146752014-08-11 20:20:55 +00002090 self.check_namespace_indentation = False
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002091
2092 def CheckBegin(self, filename, clean_lines, linenum, error):
2093 """Run checks that applies to text up to the opening brace.
2094
2095 This is mostly for checking the text after the class identifier
2096 and the "{", usually where the base class is specified. For other
2097 blocks, there isn't much to check, so we always pass.
2098
2099 Args:
2100 filename: The name of the current file.
2101 clean_lines: A CleansedLines instance containing the file.
2102 linenum: The number of the line to check.
2103 error: The function to call with any errors found.
2104 """
2105 pass
2106
2107 def CheckEnd(self, filename, clean_lines, linenum, error):
2108 """Run checks that applies to text after the closing brace.
2109
2110 This is mostly used for checking end of namespace comments.
2111
2112 Args:
2113 filename: The name of the current file.
2114 clean_lines: A CleansedLines instance containing the file.
2115 linenum: The number of the line to check.
2116 error: The function to call with any errors found.
2117 """
2118 pass
2119
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002120 def IsBlockInfo(self):
2121 """Returns true if this block is a _BlockInfo.
2122
2123 This is convenient for verifying that an object is an instance of
2124 a _BlockInfo, but not an instance of any of the derived classes.
2125
2126 Returns:
2127 True for this class, False for derived classes.
2128 """
2129 return self.__class__ == _BlockInfo
2130
2131
2132class _ExternCInfo(_BlockInfo):
2133 """Stores information about an 'extern "C"' block."""
2134
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002135 def __init__(self, linenum):
2136 _BlockInfo.__init__(self, linenum, True)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002137
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002138
2139class _ClassInfo(_BlockInfo):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002140 """Stores information about a class."""
2141
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002142 def __init__(self, name, class_or_struct, clean_lines, linenum):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002143 _BlockInfo.__init__(self, linenum, False)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002144 self.name = name
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002145 self.is_derived = False
avakulenko@google.com59146752014-08-11 20:20:55 +00002146 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002147 if class_or_struct == 'struct':
2148 self.access = 'public'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002149 self.is_struct = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002150 else:
2151 self.access = 'private'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002152 self.is_struct = False
2153
2154 # Remember initial indentation level for this class. Using raw_lines here
2155 # instead of elided to account for leading comments.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002156 self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002157
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002158 # Try to find the end of the class. This will be confused by things like:
2159 # class A {
2160 # } *x = { ...
2161 #
2162 # But it's still good enough for CheckSectionSpacing.
2163 self.last_line = 0
2164 depth = 0
2165 for i in range(linenum, clean_lines.NumLines()):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002166 line = clean_lines.elided[i]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002167 depth += line.count('{') - line.count('}')
2168 if not depth:
2169 self.last_line = i
2170 break
2171
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002172 def CheckBegin(self, filename, clean_lines, linenum, error):
2173 # Look for a bare ':'
2174 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2175 self.is_derived = True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002176
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002177 def CheckEnd(self, filename, clean_lines, linenum, error):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002178 # If there is a DISALLOW macro, it should appear near the end of
2179 # the class.
2180 seen_last_thing_in_class = False
2181 for i in xrange(linenum - 1, self.starting_linenum, -1):
2182 match = Search(
2183 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2184 self.name + r'\)',
2185 clean_lines.elided[i])
2186 if match:
2187 if seen_last_thing_in_class:
2188 error(filename, i, 'readability/constructors', 3,
2189 match.group(1) + ' should be the last thing in the class')
2190 break
2191
2192 if not Match(r'^\s*$', clean_lines.elided[i]):
2193 seen_last_thing_in_class = True
2194
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002195 # Check that closing brace is aligned with beginning of the class.
2196 # Only do this if the closing brace is indented by only whitespaces.
2197 # This means we will not check single-line class definitions.
2198 indent = Match(r'^( *)\}', clean_lines.elided[linenum])
2199 if indent and len(indent.group(1)) != self.class_indent:
2200 if self.is_struct:
2201 parent = 'struct ' + self.name
2202 else:
2203 parent = 'class ' + self.name
2204 error(filename, linenum, 'whitespace/indent', 3,
2205 'Closing brace should be aligned with beginning of %s' % parent)
2206
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002207
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002208class _NamespaceInfo(_BlockInfo):
2209 """Stores information about a namespace."""
2210
2211 def __init__(self, name, linenum):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002212 _BlockInfo.__init__(self, linenum, False)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002213 self.name = name or ''
avakulenko@google.com59146752014-08-11 20:20:55 +00002214 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002215
2216 def CheckEnd(self, filename, clean_lines, linenum, error):
2217 """Check end of namespace comments."""
2218 line = clean_lines.raw_lines[linenum]
2219
2220 # Check how many lines is enclosed in this namespace. Don't issue
2221 # warning for missing namespace comments if there aren't enough
2222 # lines. However, do apply checks if there is already an end of
2223 # namespace comment and it's incorrect.
2224 #
2225 # TODO(unknown): We always want to check end of namespace comments
2226 # if a namespace is large, but sometimes we also want to apply the
2227 # check if a short namespace contained nontrivial things (something
2228 # other than forward declarations). There is currently no logic on
2229 # deciding what these nontrivial things are, so this check is
2230 # triggered by namespace size only, which works most of the time.
2231 if (linenum - self.starting_linenum < 10
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002232 and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002233 return
2234
2235 # Look for matching comment at end of namespace.
2236 #
2237 # Note that we accept C style "/* */" comments for terminating
2238 # namespaces, so that code that terminate namespaces inside
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002239 # preprocessor macros can be cpplint clean.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002240 #
2241 # We also accept stuff like "// end of namespace <name>." with the
2242 # period at the end.
2243 #
2244 # Besides these, we don't accept anything else, otherwise we might
2245 # get false negatives when existing comment is a substring of the
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002246 # expected namespace.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002247 if self.name:
2248 # Named namespace
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002249 if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
2250 re.escape(self.name) + r'[\*/\.\\\s]*$'),
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002251 line):
2252 error(filename, linenum, 'readability/namespace', 5,
2253 'Namespace should be terminated with "// namespace %s"' %
2254 self.name)
2255 else:
2256 # Anonymous namespace
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002257 if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002258 # If "// namespace anonymous" or "// anonymous namespace (more text)",
2259 # mention "// anonymous namespace" as an acceptable form
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002260 if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002261 error(filename, linenum, 'readability/namespace', 5,
2262 'Anonymous namespace should be terminated with "// namespace"'
2263 ' or "// anonymous namespace"')
2264 else:
2265 error(filename, linenum, 'readability/namespace', 5,
2266 'Anonymous namespace should be terminated with "// namespace"')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002267
2268
2269class _PreprocessorInfo(object):
2270 """Stores checkpoints of nesting stacks when #if/#else is seen."""
2271
2272 def __init__(self, stack_before_if):
2273 # The entire nesting stack before #if
2274 self.stack_before_if = stack_before_if
2275
2276 # The entire nesting stack up to #else
2277 self.stack_before_else = []
2278
2279 # Whether we have already seen #else or #elif
2280 self.seen_else = False
2281
2282
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002283class NestingState(object):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002284 """Holds states related to parsing braces."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002285
2286 def __init__(self):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002287 # Stack for tracking all braces. An object is pushed whenever we
2288 # see a "{", and popped when we see a "}". Only 3 types of
2289 # objects are possible:
2290 # - _ClassInfo: a class or struct.
2291 # - _NamespaceInfo: a namespace.
2292 # - _BlockInfo: some other type of block.
2293 self.stack = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002294
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002295 # Top of the previous stack before each Update().
2296 #
2297 # Because the nesting_stack is updated at the end of each line, we
2298 # had to do some convoluted checks to find out what is the current
2299 # scope at the beginning of the line. This check is simplified by
2300 # saving the previous top of nesting stack.
2301 #
2302 # We could save the full stack, but we only need the top. Copying
2303 # the full nesting stack would slow down cpplint by ~10%.
2304 self.previous_stack_top = []
2305
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002306 # Stack of _PreprocessorInfo objects.
2307 self.pp_stack = []
2308
2309 def SeenOpenBrace(self):
2310 """Check if we have seen the opening brace for the innermost block.
2311
2312 Returns:
2313 True if we have seen the opening brace, False if the innermost
2314 block is still expecting an opening brace.
2315 """
2316 return (not self.stack) or self.stack[-1].seen_open_brace
2317
2318 def InNamespaceBody(self):
2319 """Check if we are currently one level inside a namespace body.
2320
2321 Returns:
2322 True if top of the stack is a namespace block, False otherwise.
2323 """
2324 return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
2325
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002326 def InExternC(self):
2327 """Check if we are currently one level inside an 'extern "C"' block.
2328
2329 Returns:
2330 True if top of the stack is an extern block, False otherwise.
2331 """
2332 return self.stack and isinstance(self.stack[-1], _ExternCInfo)
2333
2334 def InClassDeclaration(self):
2335 """Check if we are currently one level inside a class or struct declaration.
2336
2337 Returns:
2338 True if top of the stack is a class/struct, False otherwise.
2339 """
2340 return self.stack and isinstance(self.stack[-1], _ClassInfo)
2341
2342 def InAsmBlock(self):
2343 """Check if we are currently one level inside an inline ASM block.
2344
2345 Returns:
2346 True if the top of the stack is a block containing inline ASM.
2347 """
2348 return self.stack and self.stack[-1].inline_asm != _NO_ASM
2349
2350 def InTemplateArgumentList(self, clean_lines, linenum, pos):
2351 """Check if current position is inside template argument list.
2352
2353 Args:
2354 clean_lines: A CleansedLines instance containing the file.
2355 linenum: The number of the line to check.
2356 pos: position just after the suspected template argument.
2357 Returns:
2358 True if (linenum, pos) is inside template arguments.
2359 """
2360 while linenum < clean_lines.NumLines():
2361 # Find the earliest character that might indicate a template argument
2362 line = clean_lines.elided[linenum]
2363 match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2364 if not match:
2365 linenum += 1
2366 pos = 0
2367 continue
2368 token = match.group(1)
2369 pos += len(match.group(0))
2370
2371 # These things do not look like template argument list:
2372 # class Suspect {
2373 # class Suspect x; }
2374 if token in ('{', '}', ';'): return False
2375
2376 # These things look like template argument list:
2377 # template <class Suspect>
2378 # template <class Suspect = default_value>
2379 # template <class Suspect[]>
2380 # template <class Suspect...>
2381 if token in ('>', '=', '[', ']', '.'): return True
2382
2383 # Check if token is an unmatched '<'.
2384 # If not, move on to the next character.
2385 if token != '<':
2386 pos += 1
2387 if pos >= len(line):
2388 linenum += 1
2389 pos = 0
2390 continue
2391
2392 # We can't be sure if we just find a single '<', and need to
2393 # find the matching '>'.
2394 (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
2395 if end_pos < 0:
2396 # Not sure if template argument list or syntax error in file
2397 return False
2398 linenum = end_line
2399 pos = end_pos
2400 return False
2401
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002402 def UpdatePreprocessor(self, line):
2403 """Update preprocessor stack.
2404
2405 We need to handle preprocessors due to classes like this:
2406 #ifdef SWIG
2407 struct ResultDetailsPageElementExtensionPoint {
2408 #else
2409 struct ResultDetailsPageElementExtensionPoint : public Extension {
2410 #endif
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002411
2412 We make the following assumptions (good enough for most files):
2413 - Preprocessor condition evaluates to true from #if up to first
2414 #else/#elif/#endif.
2415
2416 - Preprocessor condition evaluates to false from #else/#elif up
2417 to #endif. We still perform lint checks on these lines, but
2418 these do not affect nesting stack.
2419
2420 Args:
2421 line: current line to check.
2422 """
2423 if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2424 # Beginning of #if block, save the nesting stack here. The saved
2425 # stack will allow us to restore the parsing state in the #else case.
2426 self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
2427 elif Match(r'^\s*#\s*(else|elif)\b', line):
2428 # Beginning of #else block
2429 if self.pp_stack:
2430 if not self.pp_stack[-1].seen_else:
2431 # This is the first #else or #elif block. Remember the
2432 # whole nesting stack up to this point. This is what we
2433 # keep after the #endif.
2434 self.pp_stack[-1].seen_else = True
2435 self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
2436
2437 # Restore the stack to how it was before the #if
2438 self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
2439 else:
2440 # TODO(unknown): unexpected #else, issue warning?
2441 pass
2442 elif Match(r'^\s*#\s*endif\b', line):
2443 # End of #if or #else blocks.
2444 if self.pp_stack:
2445 # If we saw an #else, we will need to restore the nesting
2446 # stack to its former state before the #else, otherwise we
2447 # will just continue from where we left off.
2448 if self.pp_stack[-1].seen_else:
2449 # Here we can just use a shallow copy since we are the last
2450 # reference to it.
2451 self.stack = self.pp_stack[-1].stack_before_else
2452 # Drop the corresponding #if
2453 self.pp_stack.pop()
2454 else:
2455 # TODO(unknown): unexpected #endif, issue warning?
2456 pass
2457
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002458 # TODO(unknown): Update() is too long, but we will refactor later.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002459 def Update(self, filename, clean_lines, linenum, error):
2460 """Update nesting state with current line.
2461
2462 Args:
2463 filename: The name of the current file.
2464 clean_lines: A CleansedLines instance containing the file.
2465 linenum: The number of the line to check.
2466 error: The function to call with any errors found.
2467 """
2468 line = clean_lines.elided[linenum]
2469
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002470 # Remember top of the previous nesting stack.
2471 #
2472 # The stack is always pushed/popped and not modified in place, so
2473 # we can just do a shallow copy instead of copy.deepcopy. Using
2474 # deepcopy would slow down cpplint by ~28%.
2475 if self.stack:
2476 self.previous_stack_top = self.stack[-1]
2477 else:
2478 self.previous_stack_top = None
2479
2480 # Update pp_stack
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002481 self.UpdatePreprocessor(line)
2482
2483 # Count parentheses. This is to avoid adding struct arguments to
2484 # the nesting stack.
2485 if self.stack:
2486 inner_block = self.stack[-1]
2487 depth_change = line.count('(') - line.count(')')
2488 inner_block.open_parentheses += depth_change
2489
2490 # Also check if we are starting or ending an inline assembly block.
2491 if inner_block.inline_asm in (_NO_ASM, _END_ASM):
2492 if (depth_change != 0 and
2493 inner_block.open_parentheses == 1 and
2494 _MATCH_ASM.match(line)):
2495 # Enter assembly block
2496 inner_block.inline_asm = _INSIDE_ASM
2497 else:
2498 # Not entering assembly block. If previous line was _END_ASM,
2499 # we will now shift to _NO_ASM state.
2500 inner_block.inline_asm = _NO_ASM
2501 elif (inner_block.inline_asm == _INSIDE_ASM and
2502 inner_block.open_parentheses == 0):
2503 # Exit assembly block
2504 inner_block.inline_asm = _END_ASM
2505
2506 # Consume namespace declaration at the beginning of the line. Do
2507 # this in a loop so that we catch same line declarations like this:
2508 # namespace proto2 { namespace bridge { class MessageSet; } }
2509 while True:
2510 # Match start of namespace. The "\b\s*" below catches namespace
2511 # declarations even if it weren't followed by a whitespace, this
2512 # is so that we don't confuse our namespace checker. The
2513 # missing spaces will be flagged by CheckSpacing.
2514 namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2515 if not namespace_decl_match:
2516 break
2517
2518 new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
2519 self.stack.append(new_namespace)
2520
2521 line = namespace_decl_match.group(2)
2522 if line.find('{') != -1:
2523 new_namespace.seen_open_brace = True
2524 line = line[line.find('{') + 1:]
2525
2526 # Look for a class declaration in whatever is left of the line
2527 # after parsing namespaces. The regexp accounts for decorated classes
2528 # such as in:
2529 # class LOCKABLE API Object {
2530 # };
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002531 class_decl_match = Match(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002532 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
Clemens Hammacher2cc6e252018-12-20 08:40:19 +00002533 r'(class|struct)\s+(?:[A-Z0-9_]+\s+)*(\w+(?:::\w+)*))'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002534 r'(.*)$', line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002535 if (class_decl_match and
2536 (not self.stack or self.stack[-1].open_parentheses == 0)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002537 # We do not want to accept classes that are actually template arguments:
2538 # template <class Ignore1,
2539 # class Ignore2 = Default<Args>,
2540 # template <Args> class Ignore3>
2541 # void Function() {};
2542 #
2543 # To avoid template argument cases, we scan forward and look for
2544 # an unmatched '>'. If we see one, assume we are inside a
2545 # template argument list.
2546 end_declaration = len(class_decl_match.group(1))
2547 if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
2548 self.stack.append(_ClassInfo(
2549 class_decl_match.group(3), class_decl_match.group(2),
2550 clean_lines, linenum))
2551 line = class_decl_match.group(4)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002552
2553 # If we have not yet seen the opening brace for the innermost block,
2554 # run checks here.
2555 if not self.SeenOpenBrace():
2556 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2557
2558 # Update access control if we are inside a class/struct
2559 if self.stack and isinstance(self.stack[-1], _ClassInfo):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002560 classinfo = self.stack[-1]
2561 access_match = Match(
2562 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
2563 r':(?:[^:]|$)',
2564 line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002565 if access_match:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002566 classinfo.access = access_match.group(2)
2567
2568 # Check that access keywords are indented +1 space. Skip this
2569 # check if the keywords are not preceded by whitespaces.
2570 indent = access_match.group(1)
2571 if (len(indent) != classinfo.class_indent + 1 and
2572 Match(r'^\s*$', indent)):
2573 if classinfo.is_struct:
2574 parent = 'struct ' + classinfo.name
2575 else:
2576 parent = 'class ' + classinfo.name
2577 slots = ''
2578 if access_match.group(3):
2579 slots = access_match.group(3)
2580 error(filename, linenum, 'whitespace/indent', 3,
2581 '%s%s: should be indented +1 space inside %s' % (
2582 access_match.group(2), slots, parent))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002583
2584 # Consume braces or semicolons from what's left of the line
2585 while True:
2586 # Match first brace, semicolon, or closed parenthesis.
2587 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
2588 if not matched:
2589 break
2590
2591 token = matched.group(1)
2592 if token == '{':
2593 # If namespace or class hasn't seen a opening brace yet, mark
2594 # namespace/class head as complete. Push a new block onto the
2595 # stack otherwise.
2596 if not self.SeenOpenBrace():
2597 self.stack[-1].seen_open_brace = True
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002598 elif Match(r'^extern\s*"[^"]*"\s*\{', line):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002599 self.stack.append(_ExternCInfo(linenum))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002600 else:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002601 self.stack.append(_BlockInfo(linenum, True))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002602 if _MATCH_ASM.match(line):
2603 self.stack[-1].inline_asm = _BLOCK_ASM
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002604
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002605 elif token == ';' or token == ')':
2606 # If we haven't seen an opening brace yet, but we already saw
2607 # a semicolon, this is probably a forward declaration. Pop
2608 # the stack for these.
2609 #
2610 # Similarly, if we haven't seen an opening brace yet, but we
2611 # already saw a closing parenthesis, then these are probably
2612 # function arguments with extra "class" or "struct" keywords.
2613 # Also pop these stack for these.
2614 if not self.SeenOpenBrace():
2615 self.stack.pop()
2616 else: # token == '}'
2617 # Perform end of block checks and pop the stack.
2618 if self.stack:
2619 self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2620 self.stack.pop()
2621 line = matched.group(2)
2622
2623 def InnermostClass(self):
2624 """Get class info on the top of the stack.
2625
2626 Returns:
2627 A _ClassInfo object if we are inside a class, or None otherwise.
2628 """
2629 for i in range(len(self.stack), 0, -1):
2630 classinfo = self.stack[i - 1]
2631 if isinstance(classinfo, _ClassInfo):
2632 return classinfo
2633 return None
2634
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002635 def CheckCompletedBlocks(self, filename, error):
2636 """Checks that all classes and namespaces have been completely parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002637
2638 Call this when all lines in a file have been processed.
2639 Args:
2640 filename: The name of the current file.
2641 error: The function to call with any errors found.
2642 """
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002643 # Note: This test can result in false positives if #ifdef constructs
2644 # get in the way of brace matching. See the testBuildClass test in
2645 # cpplint_unittest.py for an example of this.
2646 for obj in self.stack:
2647 if isinstance(obj, _ClassInfo):
2648 error(filename, obj.starting_linenum, 'build/class', 5,
2649 'Failed to find complete declaration of class %s' %
2650 obj.name)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002651 elif isinstance(obj, _NamespaceInfo):
2652 error(filename, obj.starting_linenum, 'build/namespaces', 5,
2653 'Failed to find complete declaration of namespace %s' %
2654 obj.name)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002655
2656
2657def CheckForNonStandardConstructs(filename, clean_lines, linenum,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002658 nesting_state, error):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002659 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002660
2661 Complain about several constructs which gcc-2 accepts, but which are
2662 not standard C++. Warning about these in lint is one way to ease the
2663 transition to new compilers.
2664 - put storage class first (e.g. "static const" instead of "const static").
2665 - "%lld" instead of %qd" in printf-type functions.
2666 - "%1$d" is non-standard in printf-type functions.
2667 - "\%" is an undefined character escape sequence.
2668 - text after #endif is not allowed.
2669 - invalid inner-style forward declaration.
2670 - >? and <? operators, and their >?= and <?= cousins.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002671
erg@google.com26970fa2009-11-17 18:07:32 +00002672 Additionally, check for constructor/destructor style violations and reference
2673 members, as it is very convenient to do so while checking for
2674 gcc-2 compliance.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002675
2676 Args:
2677 filename: The name of the current file.
2678 clean_lines: A CleansedLines instance containing the file.
2679 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002680 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002681 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002682 error: A callable to which errors are reported, which takes 4 arguments:
2683 filename, line number, error level, and message
2684 """
2685
2686 # Remove comments from the line, but leave in strings for now.
2687 line = clean_lines.lines[linenum]
2688
2689 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2690 error(filename, linenum, 'runtime/printf_format', 3,
2691 '%q in format strings is deprecated. Use %ll instead.')
2692
2693 if Search(r'printf\s*\(.*".*%\d+\$', line):
2694 error(filename, linenum, 'runtime/printf_format', 2,
2695 '%N$ formats are unconventional. Try rewriting to avoid them.')
2696
2697 # Remove escaped backslashes before looking for undefined escapes.
2698 line = line.replace('\\\\', '')
2699
2700 if Search(r'("|\').*\\(%|\[|\(|{)', line):
2701 error(filename, linenum, 'build/printf_format', 3,
2702 '%, [, (, and { are undefined character escapes. Unescape them.')
2703
2704 # For the rest, work with both comments and strings removed.
2705 line = clean_lines.elided[linenum]
2706
2707 if Search(r'\b(const|volatile|void|char|short|int|long'
2708 r'|float|double|signed|unsigned'
2709 r'|schar|u?int8|u?int16|u?int32|u?int64)'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002710 r'\s+(register|static|extern|typedef)\b',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002711 line):
2712 error(filename, linenum, 'build/storage_class', 5,
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002713 'Storage-class specifier (static, extern, typedef, etc) should be '
2714 'at the beginning of the declaration.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002715
2716 if Match(r'\s*#\s*endif\s*[^/\s]+', line):
2717 error(filename, linenum, 'build/endif_comment', 5,
2718 'Uncommented text after #endif is non-standard. Use a comment.')
2719
2720 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2721 error(filename, linenum, 'build/forward_decl', 5,
2722 'Inner-style forward declarations are invalid. Remove this line.')
2723
2724 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2725 line):
2726 error(filename, linenum, 'build/deprecated', 3,
2727 '>? and <? (max and min) operators are non-standard and deprecated.')
2728
erg@google.com26970fa2009-11-17 18:07:32 +00002729 if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2730 # TODO(unknown): Could it be expanded safely to arbitrary references,
2731 # without triggering too many false positives? The first
2732 # attempt triggered 5 warnings for mostly benign code in the regtest, hence
2733 # the restriction.
2734 # Here's the original regexp, for the reference:
2735 # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
2736 # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
2737 error(filename, linenum, 'runtime/member_string_references', 2,
2738 'const string& members are dangerous. It is much better to use '
2739 'alternatives, such as pointers or simple constants.')
2740
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002741 # Everything else in this function operates on class declarations.
2742 # Return early if the top of the nesting stack is not a class, or if
2743 # the class head is not completed yet.
2744 classinfo = nesting_state.InnermostClass()
2745 if not classinfo or not classinfo.seen_open_brace:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002746 return
2747
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002748 # The class may have been declared with namespace or classname qualifiers.
2749 # The constructor and destructor will not have those qualifiers.
2750 base_classname = classinfo.name.split('::')[-1]
2751
2752 # Look for single-argument constructors that aren't marked explicit.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002753 # Technically a valid construct, but against style.
avakulenko@google.com59146752014-08-11 20:20:55 +00002754 explicit_constructor_match = Match(
danakjd7f56752017-02-22 11:45:06 -05002755 r'\s+(?:(?:inline|constexpr)\s+)*(explicit\s+)?'
2756 r'(?:(?:inline|constexpr)\s+)*%s\s*'
avakulenko@google.com59146752014-08-11 20:20:55 +00002757 r'\(((?:[^()]|\([^()]*\))*)\)'
2758 % re.escape(base_classname),
2759 line)
2760
2761 if explicit_constructor_match:
2762 is_marked_explicit = explicit_constructor_match.group(1)
2763
2764 if not explicit_constructor_match.group(2):
2765 constructor_args = []
2766 else:
2767 constructor_args = explicit_constructor_match.group(2).split(',')
2768
2769 # collapse arguments so that commas in template parameter lists and function
2770 # argument parameter lists don't split arguments in two
2771 i = 0
2772 while i < len(constructor_args):
2773 constructor_arg = constructor_args[i]
2774 while (constructor_arg.count('<') > constructor_arg.count('>') or
2775 constructor_arg.count('(') > constructor_arg.count(')')):
2776 constructor_arg += ',' + constructor_args[i + 1]
2777 del constructor_args[i + 1]
2778 constructor_args[i] = constructor_arg
2779 i += 1
2780
2781 defaulted_args = [arg for arg in constructor_args if '=' in arg]
2782 noarg_constructor = (not constructor_args or # empty arg list
2783 # 'void' arg specifier
2784 (len(constructor_args) == 1 and
2785 constructor_args[0].strip() == 'void'))
2786 onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg
2787 not noarg_constructor) or
2788 # all but at most one arg defaulted
2789 (len(constructor_args) >= 1 and
2790 not noarg_constructor and
2791 len(defaulted_args) >= len(constructor_args) - 1))
2792 initializer_list_constructor = bool(
2793 onearg_constructor and
2794 Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
2795 copy_constructor = bool(
2796 onearg_constructor and
2797 Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
2798 % re.escape(base_classname), constructor_args[0].strip()))
2799
2800 if (not is_marked_explicit and
2801 onearg_constructor and
2802 not initializer_list_constructor and
2803 not copy_constructor):
2804 if defaulted_args:
2805 error(filename, linenum, 'runtime/explicit', 5,
2806 'Constructors callable with one argument '
2807 'should be marked explicit.')
2808 else:
2809 error(filename, linenum, 'runtime/explicit', 5,
2810 'Single-parameter constructors should be marked explicit.')
2811 elif is_marked_explicit and not onearg_constructor:
2812 if noarg_constructor:
2813 error(filename, linenum, 'runtime/explicit', 5,
2814 'Zero-parameter constructors should not be marked explicit.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002815
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002816
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002817def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002818 """Checks for the correctness of various spacing around function calls.
2819
2820 Args:
2821 filename: The name of the current file.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002822 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002823 linenum: The number of the line to check.
2824 error: The function to call with any errors found.
2825 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002826 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002827
2828 # Since function calls often occur inside if/for/while/switch
2829 # expressions - which have their own, more liberal conventions - we
2830 # first see if we should be looking inside such an expression for a
2831 # function call, to which we can apply more strict standards.
2832 fncall = line # if there's no control flow construct, look at whole line
2833 for pattern in (r'\bif\s*\((.*)\)\s*{',
2834 r'\bfor\s*\((.*)\)\s*{',
2835 r'\bwhile\s*\((.*)\)\s*[{;]',
2836 r'\bswitch\s*\((.*)\)\s*{'):
2837 match = Search(pattern, line)
2838 if match:
2839 fncall = match.group(1) # look inside the parens for function calls
2840 break
2841
2842 # Except in if/for/while/switch, there should never be space
2843 # immediately inside parens (eg "f( 3, 4 )"). We make an exception
2844 # for nested parens ( (a+b) + c ). Likewise, there should never be
2845 # a space before a ( when it's a function argument. I assume it's a
2846 # function argument when the char before the whitespace is legal in
2847 # a function name (alnum + _) and we're not starting a macro. Also ignore
2848 # pointers and references to arrays and functions coz they're too tricky:
2849 # we use a very simple way to recognize these:
2850 # " (something)(maybe-something)" or
2851 # " (something)(maybe-something," or
2852 # " (something)[something]"
2853 # Note that we assume the contents of [] to be short enough that
2854 # they'll never need to wrap.
2855 if ( # Ignore control structures.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002856 not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2857 fncall) and
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002858 # Ignore pointers/references to functions.
2859 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
2860 # Ignore pointers/references to arrays.
2861 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
erg@google.com6317a9c2009-06-25 00:28:19 +00002862 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002863 error(filename, linenum, 'whitespace/parens', 4,
2864 'Extra space after ( in function call')
erg@google.com6317a9c2009-06-25 00:28:19 +00002865 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002866 error(filename, linenum, 'whitespace/parens', 2,
2867 'Extra space after (')
2868 if (Search(r'\w\s+\(', fncall) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002869 not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002870 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002871 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
2872 not Search(r'\bcase\s+\(', fncall)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002873 # TODO(unknown): Space after an operator function seem to be a common
2874 # error, silence those for now by restricting them to highest verbosity.
2875 if Search(r'\boperator_*\b', line):
2876 error(filename, linenum, 'whitespace/parens', 0,
2877 'Extra space before ( in function call')
2878 else:
2879 error(filename, linenum, 'whitespace/parens', 4,
2880 'Extra space before ( in function call')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002881 # If the ) is followed only by a newline or a { + newline, assume it's
2882 # part of a control statement (if/while/etc), and don't complain
2883 if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002884 # If the closing parenthesis is preceded by only whitespaces,
2885 # try to give a more descriptive error message.
2886 if Search(r'^\s+\)', fncall):
2887 error(filename, linenum, 'whitespace/parens', 2,
2888 'Closing ) should be moved to the previous line')
2889 else:
2890 error(filename, linenum, 'whitespace/parens', 2,
2891 'Extra space before )')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002892
2893
2894def IsBlankLine(line):
2895 """Returns true if the given line is blank.
2896
2897 We consider a line to be blank if the line is empty or consists of
2898 only white spaces.
2899
2900 Args:
2901 line: A line of a string.
2902
2903 Returns:
2904 True, if the given line is blank.
2905 """
2906 return not line or line.isspace()
2907
2908
avakulenko@google.com59146752014-08-11 20:20:55 +00002909def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
2910 error):
2911 is_namespace_indent_item = (
2912 len(nesting_state.stack) > 1 and
2913 nesting_state.stack[-1].check_namespace_indentation and
2914 isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
2915 nesting_state.previous_stack_top == nesting_state.stack[-2])
2916
2917 if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
2918 clean_lines.elided, line):
2919 CheckItemIndentationInNamespace(filename, clean_lines.elided,
2920 line, error)
2921
2922
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002923def CheckForFunctionLengths(filename, clean_lines, linenum,
2924 function_state, error):
2925 """Reports for long function bodies.
2926
2927 For an overview why this is done, see:
Alexandr Ilinff294c32017-04-27 15:57:40 +02002928 https://google.github.io/styleguide/cppguide.html#Write_Short_Functions
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002929
2930 Uses a simplistic algorithm assuming other style guidelines
2931 (especially spacing) are followed.
2932 Only checks unindented functions, so class members are unchecked.
2933 Trivial bodies are unchecked, so constructors with huge initializer lists
2934 may be missed.
2935 Blank/comment lines are not counted so as to avoid encouraging the removal
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002936 of vertical space and comments just to get through a lint check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002937 NOLINT *on the last line of a function* disables this check.
2938
2939 Args:
2940 filename: The name of the current file.
2941 clean_lines: A CleansedLines instance containing the file.
2942 linenum: The number of the line to check.
2943 function_state: Current function name and lines in body so far.
2944 error: The function to call with any errors found.
2945 """
2946 lines = clean_lines.lines
2947 line = lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002948 joined_line = ''
2949
2950 starting_func = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002951 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002952 match_result = Match(regexp, line)
2953 if match_result:
2954 # If the name is all caps and underscores, figure it's a macro and
2955 # ignore it, unless it's TEST or TEST_F.
2956 function_name = match_result.group(1).split()[-1]
2957 if function_name == 'TEST' or function_name == 'TEST_F' or (
2958 not Match(r'[A-Z_]+$', function_name)):
2959 starting_func = True
2960
2961 if starting_func:
2962 body_found = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002963 for start_linenum in xrange(linenum, clean_lines.NumLines()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002964 start_line = lines[start_linenum]
2965 joined_line += ' ' + start_line.lstrip()
2966 if Search(r'(;|})', start_line): # Declarations and trivial functions
2967 body_found = True
2968 break # ... ignore
2969 elif Search(r'{', start_line):
2970 body_found = True
2971 function = Search(r'((\w|:)*)\(', line).group(1)
2972 if Match(r'TEST', function): # Handle TEST... macros
2973 parameter_regexp = Search(r'(\(.*\))', joined_line)
2974 if parameter_regexp: # Ignore bad syntax
2975 function += parameter_regexp.group(1)
2976 else:
2977 function += '()'
2978 function_state.Begin(function)
2979 break
2980 if not body_found:
erg@google.com6317a9c2009-06-25 00:28:19 +00002981 # No body for the function (or evidence of a non-function) was found.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002982 error(filename, linenum, 'readability/fn_size', 5,
2983 'Lint failed to find start of function body.')
2984 elif Match(r'^\}\s*$', line): # function end
erg@google.com35589e62010-11-17 18:58:16 +00002985 function_state.Check(error, filename, linenum)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002986 function_state.End()
2987 elif not Match(r'^\s*$', line):
2988 function_state.Count() # Count non-blank/non-comment lines.
2989
2990
2991_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2992
2993
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002994def CheckComment(line, filename, linenum, next_line_start, error):
2995 """Checks for common mistakes in comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002996
2997 Args:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002998 line: The line in question.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002999 filename: The name of the current file.
3000 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003001 next_line_start: The first non-whitespace column of the next line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003002 error: The function to call with any errors found.
3003 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003004 commentpos = line.find('//')
3005 if commentpos != -1:
3006 # Check if the // may be in quotes. If so, ignore it
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003007 if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003008 # Allow one space for new scopes, two spaces otherwise:
3009 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
3010 ((commentpos >= 1 and
3011 line[commentpos-1] not in string.whitespace) or
3012 (commentpos >= 2 and
3013 line[commentpos-2] not in string.whitespace))):
3014 error(filename, linenum, 'whitespace/comments', 2,
3015 'At least two spaces is best between code and comments')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003016
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003017 # Checks for common mistakes in TODO comments.
3018 comment = line[commentpos:]
3019 match = _RE_PATTERN_TODO.match(comment)
3020 if match:
3021 # One whitespace is correct; zero whitespace is handled elsewhere.
3022 leading_whitespace = match.group(1)
3023 if len(leading_whitespace) > 1:
3024 error(filename, linenum, 'whitespace/todo', 2,
3025 'Too many spaces before TODO')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003026
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003027 username = match.group(2)
3028 if not username:
3029 error(filename, linenum, 'readability/todo', 2,
3030 'Missing username in TODO; it should look like '
3031 '"// TODO(my_username): Stuff."')
3032
3033 middle_whitespace = match.group(3)
3034 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
3035 if middle_whitespace != ' ' and middle_whitespace != '':
3036 error(filename, linenum, 'whitespace/todo', 2,
3037 'TODO(my_username) should be followed by a space')
3038
3039 # If the comment contains an alphanumeric character, there
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003040 # should be a space somewhere between it and the // unless
3041 # it's a /// or //! Doxygen comment.
3042 if (Match(r'//[^ ]*\w', comment) and
3043 not Match(r'(///|//\!)(\s+|$)', comment)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003044 error(filename, linenum, 'whitespace/comments', 4,
3045 'Should have a space between // and comment')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003046
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003047
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003048def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003049 """Checks for the correctness of various spacing issues in the code.
3050
3051 Things we check for: spaces around operators, spaces after
3052 if/for/while/switch, no spaces around parens in function calls, two
3053 spaces between code and comment, don't start a block with a blank
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003054 line, don't end a function with a blank line, don't add a blank line
3055 after public/protected/private, don't have too many blank lines in a row.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003056
3057 Args:
3058 filename: The name of the current file.
3059 clean_lines: A CleansedLines instance containing the file.
3060 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003061 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003062 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003063 error: The function to call with any errors found.
3064 """
3065
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003066 # Don't use "elided" lines here, otherwise we can't check commented lines.
3067 # Don't want to use "raw" either, because we don't want to check inside C++11
3068 # raw strings,
3069 raw = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003070 line = raw[linenum]
3071
3072 # Before nixing comments, check if the line is blank for no good
3073 # reason. This includes the first line after a block is opened, and
3074 # blank lines at the end of a function (ie, right before a line like '}'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003075 #
3076 # Skip all the blank line checks if we are immediately inside a
3077 # namespace body. In other words, don't issue blank line warnings
3078 # for this block:
3079 # namespace {
3080 #
3081 # }
3082 #
3083 # A warning about missing end of namespace comments will be issued instead.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003084 #
3085 # Also skip blank line checks for 'extern "C"' blocks, which are formatted
3086 # like namespaces.
3087 if (IsBlankLine(line) and
3088 not nesting_state.InNamespaceBody() and
3089 not nesting_state.InExternC()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003090 elided = clean_lines.elided
3091 prev_line = elided[linenum - 1]
3092 prevbrace = prev_line.rfind('{')
3093 # TODO(unknown): Don't complain if line before blank line, and line after,
3094 # both start with alnums and are indented the same amount.
3095 # This ignores whitespace at the start of a namespace block
3096 # because those are not usually indented.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003097 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003098 # OK, we have a blank line at the start of a code block. Before we
3099 # complain, we check if it is an exception to the rule: The previous
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003100 # non-empty line has the parameters of a function header that are indented
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003101 # 4 spaces (because they did not fit in a 80 column line when placed on
3102 # the same line as the function name). We also check for the case where
3103 # the previous line is indented 6 spaces, which may happen when the
3104 # initializers of a constructor do not fit into a 80 column line.
3105 exception = False
3106 if Match(r' {6}\w', prev_line): # Initializer list?
3107 # We are looking for the opening column of initializer list, which
3108 # should be indented 4 spaces to cause 6 space indentation afterwards.
3109 search_position = linenum-2
3110 while (search_position >= 0
3111 and Match(r' {6}\w', elided[search_position])):
3112 search_position -= 1
3113 exception = (search_position >= 0
3114 and elided[search_position][:5] == ' :')
3115 else:
3116 # Search for the function arguments or an initializer list. We use a
3117 # simple heuristic here: If the line is indented 4 spaces; and we have a
3118 # closing paren, without the opening paren, followed by an opening brace
3119 # or colon (for initializer lists) we assume that it is the last line of
3120 # a function header. If we have a colon indented 4 spaces, it is an
3121 # initializer list.
3122 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3123 prev_line)
3124 or Match(r' {4}:', prev_line))
3125
3126 if not exception:
3127 error(filename, linenum, 'whitespace/blank_line', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003128 'Redundant blank line at the start of a code block '
3129 'should be deleted.')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003130 # Ignore blank lines at the end of a block in a long if-else
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003131 # chain, like this:
3132 # if (condition1) {
3133 # // Something followed by a blank line
3134 #
3135 # } else if (condition2) {
3136 # // Something else
3137 # }
3138 if linenum + 1 < clean_lines.NumLines():
3139 next_line = raw[linenum + 1]
3140 if (next_line
3141 and Match(r'\s*}', next_line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003142 and next_line.find('} else ') == -1):
3143 error(filename, linenum, 'whitespace/blank_line', 3,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003144 'Redundant blank line at the end of a code block '
3145 'should be deleted.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003146
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003147 matched = Match(r'\s*(public|protected|private):', prev_line)
3148 if matched:
3149 error(filename, linenum, 'whitespace/blank_line', 3,
3150 'Do not leave a blank line after "%s:"' % matched.group(1))
3151
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003152 # Next, check comments
3153 next_line_start = 0
3154 if linenum + 1 < clean_lines.NumLines():
3155 next_line = raw[linenum + 1]
3156 next_line_start = len(next_line) - len(next_line.lstrip())
3157 CheckComment(line, filename, linenum, next_line_start, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003158
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003159 # get rid of comments and strings
3160 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003161
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003162 # You shouldn't have spaces before your brackets, except maybe after
3163 # 'delete []' or 'return []() {};'
3164 if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
3165 error(filename, linenum, 'whitespace/braces', 5,
3166 'Extra space before [')
3167
3168 # In range-based for, we wanted spaces before and after the colon, but
3169 # not around "::" tokens that might appear.
3170 if (Search(r'for *\(.*[^:]:[^: ]', line) or
3171 Search(r'for *\(.*[^: ]:[^:]', line)):
3172 error(filename, linenum, 'whitespace/forcolon', 2,
3173 'Missing space around colon in range-based for loop')
3174
3175
3176def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3177 """Checks for horizontal spacing around operators.
3178
3179 Args:
3180 filename: The name of the current file.
3181 clean_lines: A CleansedLines instance containing the file.
3182 linenum: The number of the line to check.
3183 error: The function to call with any errors found.
3184 """
3185 line = clean_lines.elided[linenum]
3186
3187 # Don't try to do spacing checks for operator methods. Do this by
3188 # replacing the troublesome characters with something else,
3189 # preserving column position for all other characters.
3190 #
3191 # The replacement is done repeatedly to avoid false positives from
3192 # operators that call operators.
3193 while True:
3194 match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3195 if match:
3196 line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
3197 else:
3198 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003199
3200 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
3201 # Otherwise not. Note we only check for non-spaces on *both* sides;
3202 # sometimes people put non-spaces on one side when aligning ='s among
3203 # many lines (not that this is behavior that I approve of...)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003204 if ((Search(r'[\w.]=', line) or
3205 Search(r'=[\w.]', line))
3206 and not Search(r'\b(if|while|for) ', line)
3207 # Operators taken from [lex.operators] in C++11 standard.
3208 and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3209 and not Search(r'operator=', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003210 error(filename, linenum, 'whitespace/operators', 4,
3211 'Missing spaces around =')
3212
3213 # It's ok not to have spaces around binary operators like + - * /, but if
3214 # there's too little whitespace, we get concerned. It's hard to tell,
3215 # though, so we punt on this one for now. TODO.
3216
3217 # You should always have whitespace around binary operators.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003218 #
3219 # Check <= and >= first to avoid false positives with < and >, then
3220 # check non-include lines for spacing around < and >.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003221 #
3222 # If the operator is followed by a comma, assume it's be used in a
3223 # macro context and don't do any checks. This avoids false
3224 # positives.
3225 #
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003226 # Note that && is not included here. This is because there are too
3227 # many false positives due to RValue references.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003228 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003229 if match:
3230 error(filename, linenum, 'whitespace/operators', 3,
3231 'Missing spaces around %s' % match.group(1))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003232 elif not Match(r'#.*include', line):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003233 # Look for < that is not surrounded by spaces. This is only
3234 # triggered if both sides are missing spaces, even though
3235 # technically should should flag if at least one side is missing a
3236 # space. This is done to avoid some false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003237 match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
3238 if match:
3239 (_, _, end_pos) = CloseExpression(
3240 clean_lines, linenum, len(match.group(1)))
3241 if end_pos <= -1:
3242 error(filename, linenum, 'whitespace/operators', 3,
3243 'Missing spaces around <')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003244
3245 # Look for > that is not surrounded by spaces. Similar to the
3246 # above, we only trigger if both sides are missing spaces to avoid
3247 # false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003248 match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
3249 if match:
3250 (_, _, start_pos) = ReverseCloseExpression(
3251 clean_lines, linenum, len(match.group(1)))
3252 if start_pos <= -1:
3253 error(filename, linenum, 'whitespace/operators', 3,
3254 'Missing spaces around >')
3255
3256 # We allow no-spaces around << when used like this: 10<<20, but
3257 # not otherwise (particularly, not when used as streams)
avakulenko@google.com59146752014-08-11 20:20:55 +00003258 #
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003259 # We also allow operators following an opening parenthesis, since
3260 # those tend to be macros that deal with operators.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003261 match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003262 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003263 not (match.group(1) == 'operator' and match.group(2) == ';')):
3264 error(filename, linenum, 'whitespace/operators', 3,
3265 'Missing spaces around <<')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003266
3267 # We allow no-spaces around >> for almost anything. This is because
3268 # C++11 allows ">>" to close nested templates, which accounts for
3269 # most cases when ">>" is not followed by a space.
3270 #
3271 # We still warn on ">>" followed by alpha character, because that is
3272 # likely due to ">>" being used for right shifts, e.g.:
3273 # value >> alpha
3274 #
3275 # When ">>" is used to close templates, the alphanumeric letter that
3276 # follows would be part of an identifier, and there should still be
3277 # a space separating the template type and the identifier.
3278 # type<type<type>> alpha
3279 match = Search(r'>>[a-zA-Z_]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003280 if match:
3281 error(filename, linenum, 'whitespace/operators', 3,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003282 'Missing spaces around >>')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003283
3284 # There shouldn't be space around unary operators
3285 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3286 if match:
3287 error(filename, linenum, 'whitespace/operators', 4,
3288 'Extra space for operator %s' % match.group(1))
3289
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003290
3291def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
3292 """Checks for horizontal spacing around parentheses.
3293
3294 Args:
3295 filename: The name of the current file.
3296 clean_lines: A CleansedLines instance containing the file.
3297 linenum: The number of the line to check.
3298 error: The function to call with any errors found.
3299 """
3300 line = clean_lines.elided[linenum]
3301
3302 # No spaces after an if, while, switch, or for
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003303 match = Search(r' (if\(|for\(|while\(|switch\()', line)
3304 if match:
3305 error(filename, linenum, 'whitespace/parens', 5,
3306 'Missing space before ( in %s' % match.group(1))
3307
3308 # For if/for/while/switch, the left and right parens should be
3309 # consistent about how many spaces are inside the parens, and
3310 # there should either be zero or one spaces inside the parens.
3311 # We don't want: "if ( foo)" or "if ( foo )".
erg@google.com6317a9c2009-06-25 00:28:19 +00003312 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003313 match = Search(r'\b(if|for|while|switch)\s*'
3314 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3315 line)
3316 if match:
3317 if len(match.group(2)) != len(match.group(4)):
3318 if not (match.group(3) == ';' and
erg@google.com6317a9c2009-06-25 00:28:19 +00003319 len(match.group(2)) == 1 + len(match.group(4)) or
3320 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003321 error(filename, linenum, 'whitespace/parens', 5,
3322 'Mismatching spaces inside () in %s' % match.group(1))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003323 if len(match.group(2)) not in [0, 1]:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003324 error(filename, linenum, 'whitespace/parens', 5,
3325 'Should have zero or one spaces inside ( and ) in %s' %
3326 match.group(1))
3327
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003328
3329def CheckCommaSpacing(filename, clean_lines, linenum, error):
3330 """Checks for horizontal spacing near commas and semicolons.
3331
3332 Args:
3333 filename: The name of the current file.
3334 clean_lines: A CleansedLines instance containing the file.
3335 linenum: The number of the line to check.
3336 error: The function to call with any errors found.
3337 """
3338 raw = clean_lines.lines_without_raw_strings
3339 line = clean_lines.elided[linenum]
3340
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003341 # 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 +00003342 #
3343 # This does not apply when the non-space character following the
3344 # comma is another comma, since the only time when that happens is
3345 # for empty macro arguments.
3346 #
3347 # We run this check in two passes: first pass on elided lines to
3348 # verify that lines contain missing whitespaces, second pass on raw
3349 # lines to confirm that those missing whitespaces are not due to
3350 # elided comments.
avakulenko@google.com59146752014-08-11 20:20:55 +00003351 if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
3352 Search(r',[^,\s]', raw[linenum])):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003353 error(filename, linenum, 'whitespace/comma', 3,
3354 'Missing space after ,')
3355
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003356 # You should always have a space after a semicolon
3357 # except for few corner cases
3358 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
3359 # space after ;
3360 if Search(r';[^\s};\\)/]', line):
3361 error(filename, linenum, 'whitespace/semicolon', 3,
3362 'Missing space after ;')
3363
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003364
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003365def _IsType(clean_lines, nesting_state, expr):
3366 """Check if expression looks like a type name, returns true if so.
3367
3368 Args:
3369 clean_lines: A CleansedLines instance containing the file.
3370 nesting_state: A NestingState instance which maintains information about
3371 the current stack of nested blocks being parsed.
3372 expr: The expression to check.
3373 Returns:
3374 True, if token looks like a type.
3375 """
3376 # Keep only the last token in the expression
3377 last_word = Match(r'^.*(\b\S+)$', expr)
3378 if last_word:
3379 token = last_word.group(1)
3380 else:
3381 token = expr
3382
3383 # Match native types and stdint types
3384 if _TYPES.match(token):
3385 return True
3386
3387 # Try a bit harder to match templated types. Walk up the nesting
3388 # stack until we find something that resembles a typename
3389 # declaration for what we are looking for.
3390 typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) +
3391 r'\b')
3392 block_index = len(nesting_state.stack) - 1
3393 while block_index >= 0:
3394 if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
3395 return False
3396
3397 # Found where the opening brace is. We want to scan from this
3398 # line up to the beginning of the function, minus a few lines.
3399 # template <typename Type1, // stop scanning here
3400 # ...>
3401 # class C
3402 # : public ... { // start scanning here
3403 last_line = nesting_state.stack[block_index].starting_linenum
3404
3405 next_block_start = 0
3406 if block_index > 0:
3407 next_block_start = nesting_state.stack[block_index - 1].starting_linenum
3408 first_line = last_line
3409 while first_line >= next_block_start:
3410 if clean_lines.elided[first_line].find('template') >= 0:
3411 break
3412 first_line -= 1
3413 if first_line < next_block_start:
3414 # Didn't find any "template" keyword before reaching the next block,
3415 # there are probably no template things to check for this block
3416 block_index -= 1
3417 continue
3418
3419 # Look for typename in the specified range
3420 for i in xrange(first_line, last_line + 1, 1):
3421 if Search(typename_pattern, clean_lines.elided[i]):
3422 return True
3423 block_index -= 1
3424
3425 return False
3426
3427
3428def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003429 """Checks for horizontal spacing near commas.
3430
3431 Args:
3432 filename: The name of the current file.
3433 clean_lines: A CleansedLines instance containing the file.
3434 linenum: The number of the line to check.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003435 nesting_state: A NestingState instance which maintains information about
3436 the current stack of nested blocks being parsed.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003437 error: The function to call with any errors found.
3438 """
3439 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003440
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003441 # Except after an opening paren, or after another opening brace (in case of
3442 # an initializer list, for instance), you should have spaces before your
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003443 # braces when they are delimiting blocks, classes, namespaces etc.
3444 # And since you should never have braces at the beginning of a line,
3445 # this is an easy test. Except that braces used for initialization don't
3446 # follow the same rule; we often don't want spaces before those.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003447 match = Match(r'^(.*[^ ({>]){', line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003448
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003449 if match:
3450 # Try a bit harder to check for brace initialization. This
3451 # happens in one of the following forms:
3452 # Constructor() : initializer_list_{} { ... }
3453 # Constructor{}.MemberFunction()
3454 # Type variable{};
3455 # FunctionCall(type{}, ...);
3456 # LastArgument(..., type{});
3457 # LOG(INFO) << type{} << " ...";
3458 # map_of_type[{...}] = ...;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003459 # ternary = expr ? new type{} : nullptr;
3460 # OuterTemplate<InnerTemplateConstructor<Type>{}>
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003461 #
3462 # We check for the character following the closing brace, and
3463 # silence the warning if it's one of those listed above, i.e.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003464 # "{.;,)<>]:".
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003465 #
3466 # To account for nested initializer list, we allow any number of
3467 # closing braces up to "{;,)<". We can't simply silence the
3468 # warning on first sight of closing brace, because that would
3469 # cause false negatives for things that are not initializer lists.
3470 # Silence this: But not this:
3471 # Outer{ if (...) {
3472 # Inner{...} if (...){ // Missing space before {
3473 # }; }
3474 #
3475 # There is a false negative with this approach if people inserted
3476 # spurious semicolons, e.g. "if (cond){};", but we will catch the
3477 # spurious semicolon with a separate check.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003478 leading_text = match.group(1)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003479 (endline, endlinenum, endpos) = CloseExpression(
3480 clean_lines, linenum, len(match.group(1)))
3481 trailing_text = ''
3482 if endpos > -1:
3483 trailing_text = endline[endpos:]
3484 for offset in xrange(endlinenum + 1,
3485 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3486 trailing_text += clean_lines.elided[offset]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003487 # We also suppress warnings for `uint64_t{expression}` etc., as the style
3488 # guide recommends brace initialization for integral types to avoid
3489 # overflow/truncation.
3490 if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
3491 and not _IsType(clean_lines, nesting_state, leading_text)):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003492 error(filename, linenum, 'whitespace/braces', 5,
3493 'Missing space before {')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003494
3495 # Make sure '} else {' has spaces.
3496 if Search(r'}else', line):
3497 error(filename, linenum, 'whitespace/braces', 5,
3498 'Missing space before else')
3499
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003500 # You shouldn't have a space before a semicolon at the end of the line.
3501 # There's a special case for "for" since the style guide allows space before
3502 # the semicolon there.
3503 if Search(r':\s*;\s*$', line):
3504 error(filename, linenum, 'whitespace/semicolon', 5,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003505 'Semicolon defining empty statement. Use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003506 elif Search(r'^\s*;\s*$', line):
3507 error(filename, linenum, 'whitespace/semicolon', 5,
3508 'Line contains only semicolon. If this should be an empty statement, '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003509 'use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003510 elif (Search(r'\s+;\s*$', line) and
3511 not Search(r'\bfor\b', line)):
3512 error(filename, linenum, 'whitespace/semicolon', 5,
3513 'Extra space before last semicolon. If this should be an empty '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003514 'statement, use {} instead.')
3515
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003516
3517def IsDecltype(clean_lines, linenum, column):
3518 """Check if the token ending on (linenum, column) is decltype().
3519
3520 Args:
3521 clean_lines: A CleansedLines instance containing the file.
3522 linenum: the number of the line to check.
3523 column: end column of the token to check.
3524 Returns:
3525 True if this token is decltype() expression, False otherwise.
3526 """
3527 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
3528 if start_col < 0:
3529 return False
3530 if Search(r'\bdecltype\s*$', text[0:start_col]):
3531 return True
3532 return False
3533
3534
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003535def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
3536 """Checks for additional blank line issues related to sections.
3537
3538 Currently the only thing checked here is blank line before protected/private.
3539
3540 Args:
3541 filename: The name of the current file.
3542 clean_lines: A CleansedLines instance containing the file.
3543 class_info: A _ClassInfo objects.
3544 linenum: The number of the line to check.
3545 error: The function to call with any errors found.
3546 """
3547 # Skip checks if the class is small, where small means 25 lines or less.
3548 # 25 lines seems like a good cutoff since that's the usual height of
3549 # terminals, and any class that can't fit in one screen can't really
3550 # be considered "small".
3551 #
3552 # Also skip checks if we are on the first line. This accounts for
3553 # classes that look like
3554 # class Foo { public: ... };
3555 #
3556 # If we didn't find the end of the class, last_line would be zero,
3557 # and the check will be skipped by the first condition.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003558 if (class_info.last_line - class_info.starting_linenum <= 24 or
3559 linenum <= class_info.starting_linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003560 return
3561
3562 matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
3563 if matched:
3564 # Issue warning if the line before public/protected/private was
3565 # not a blank line, but don't do this if the previous line contains
3566 # "class" or "struct". This can happen two ways:
3567 # - We are at the beginning of the class.
3568 # - We are forward-declaring an inner class that is semantically
3569 # private, but needed to be public for implementation reasons.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003570 # Also ignores cases where the previous line ends with a backslash as can be
3571 # common when defining classes in C macros.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003572 prev_line = clean_lines.lines[linenum - 1]
3573 if (not IsBlankLine(prev_line) and
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003574 not Search(r'\b(class|struct)\b', prev_line) and
3575 not Search(r'\\$', prev_line)):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003576 # Try a bit harder to find the beginning of the class. This is to
3577 # account for multi-line base-specifier lists, e.g.:
3578 # class Derived
3579 # : public Base {
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003580 end_class_head = class_info.starting_linenum
3581 for i in range(class_info.starting_linenum, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003582 if Search(r'\{\s*$', clean_lines.lines[i]):
3583 end_class_head = i
3584 break
3585 if end_class_head < linenum - 1:
3586 error(filename, linenum, 'whitespace/blank_line', 3,
3587 '"%s:" should be preceded by a blank line' % matched.group(1))
3588
3589
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003590def GetPreviousNonBlankLine(clean_lines, linenum):
3591 """Return the most recent non-blank line and its line number.
3592
3593 Args:
3594 clean_lines: A CleansedLines instance containing the file contents.
3595 linenum: The number of the line to check.
3596
3597 Returns:
3598 A tuple with two elements. The first element is the contents of the last
3599 non-blank line before the current line, or the empty string if this is the
3600 first non-blank line. The second is the line number of that line, or -1
3601 if this is the first non-blank line.
3602 """
3603
3604 prevlinenum = linenum - 1
3605 while prevlinenum >= 0:
3606 prevline = clean_lines.elided[prevlinenum]
3607 if not IsBlankLine(prevline): # if not a blank line...
3608 return (prevline, prevlinenum)
3609 prevlinenum -= 1
3610 return ('', -1)
3611
3612
3613def CheckBraces(filename, clean_lines, linenum, error):
3614 """Looks for misplaced braces (e.g. at the end of line).
3615
3616 Args:
3617 filename: The name of the current file.
3618 clean_lines: A CleansedLines instance containing the file.
3619 linenum: The number of the line to check.
3620 error: The function to call with any errors found.
3621 """
3622
3623 line = clean_lines.elided[linenum] # get rid of comments and strings
3624
3625 if Match(r'\s*{\s*$', line):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003626 # We allow an open brace to start a line in the case where someone is using
3627 # braces in a block to explicitly create a new scope, which is commonly used
3628 # to control the lifetime of stack-allocated variables. Braces are also
3629 # used for brace initializers inside function calls. We don't detect this
3630 # perfectly: we just don't complain if the last non-whitespace character on
3631 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003632 # previous line starts a preprocessor block. We also allow a brace on the
3633 # following line if it is part of an array initialization and would not fit
3634 # within the 80 character limit of the preceding line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003635 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003636 if (not Search(r'[,;:}{(]\s*$', prevline) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003637 not Match(r'\s*#', prevline) and
3638 not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003639 error(filename, linenum, 'whitespace/braces', 4,
3640 '{ should almost always be at the end of the previous line')
3641
3642 # An else clause should be on the same line as the preceding closing brace.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003643 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003644 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3645 if Match(r'\s*}\s*$', prevline):
3646 error(filename, linenum, 'whitespace/newline', 4,
3647 'An else should appear on the same line as the preceding }')
3648
3649 # If braces come on one side of an else, they should be on both.
3650 # However, we have to worry about "else if" that spans multiple lines!
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003651 if Search(r'else if\s*\(', line): # could be multi-line if
3652 brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
3653 # find the ( after the if
3654 pos = line.find('else if')
3655 pos = line.find('(', pos)
3656 if pos > 0:
3657 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
3658 brace_on_right = endline[endpos:].find('{') != -1
3659 if brace_on_left != brace_on_right: # must be brace after if
3660 error(filename, linenum, 'readability/braces', 5,
3661 'If an else has a brace on one side, it should have it on both')
3662 elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
3663 error(filename, linenum, 'readability/braces', 5,
3664 'If an else has a brace on one side, it should have it on both')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003665
3666 # Likewise, an else should never have the else clause on the same line
3667 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
3668 error(filename, linenum, 'whitespace/newline', 4,
3669 'Else clause should never be on same line as else (use 2 lines)')
3670
3671 # In the same way, a do/while should never be on one line
3672 if Match(r'\s*do [^\s{]', line):
3673 error(filename, linenum, 'whitespace/newline', 4,
3674 'do/while clauses should not be on a single line')
3675
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003676 # Check single-line if/else bodies. The style guide says 'curly braces are not
3677 # required for single-line statements'. We additionally allow multi-line,
3678 # single statements, but we reject anything with more than one semicolon in
3679 # it. This means that the first semicolon after the if should be at the end of
3680 # its line, and the line after that should have an indent level equal to or
3681 # lower than the if. We also check for ambiguous if/else nesting without
3682 # braces.
3683 if_else_match = Search(r'\b(if\s*\(|else\b)', line)
3684 if if_else_match and not Match(r'\s*#', line):
3685 if_indent = GetIndentLevel(line)
3686 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3687 if_match = Search(r'\bif\s*\(', line)
3688 if if_match:
3689 # This could be a multiline if condition, so find the end first.
3690 pos = if_match.end() - 1
3691 (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
3692 # Check for an opening brace, either directly after the if or on the next
3693 # line. If found, this isn't a single-statement conditional.
3694 if (not Match(r'\s*{', endline[endpos:])
3695 and not (Match(r'\s*$', endline[endpos:])
3696 and endlinenum < (len(clean_lines.elided) - 1)
3697 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
3698 while (endlinenum < len(clean_lines.elided)
3699 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3700 endlinenum += 1
3701 endpos = 0
3702 if endlinenum < len(clean_lines.elided):
3703 endline = clean_lines.elided[endlinenum]
3704 # We allow a mix of whitespace and closing braces (e.g. for one-liner
3705 # methods) and a single \ after the semicolon (for macros)
3706 endpos = endline.find(';')
3707 if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
avakulenko@google.com59146752014-08-11 20:20:55 +00003708 # Semicolon isn't the last character, there's something trailing.
3709 # Output a warning if the semicolon is not contained inside
3710 # a lambda expression.
3711 if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3712 endline):
3713 error(filename, linenum, 'readability/braces', 4,
3714 'If/else bodies with multiple statements require braces')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003715 elif endlinenum < len(clean_lines.elided) - 1:
3716 # Make sure the next line is dedented
3717 next_line = clean_lines.elided[endlinenum + 1]
3718 next_indent = GetIndentLevel(next_line)
3719 # With ambiguous nested if statements, this will error out on the
3720 # if that *doesn't* match the else, regardless of whether it's the
3721 # inner one or outer one.
3722 if (if_match and Match(r'\s*else\b', next_line)
3723 and next_indent != if_indent):
3724 error(filename, linenum, 'readability/braces', 4,
3725 'Else clause should be indented at the same level as if. '
3726 'Ambiguous nested if/else chains require braces.')
3727 elif next_indent > if_indent:
3728 error(filename, linenum, 'readability/braces', 4,
3729 'If/else bodies with multiple statements require braces')
3730
3731
3732def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
3733 """Looks for redundant trailing semicolon.
3734
3735 Args:
3736 filename: The name of the current file.
3737 clean_lines: A CleansedLines instance containing the file.
3738 linenum: The number of the line to check.
3739 error: The function to call with any errors found.
3740 """
3741
3742 line = clean_lines.elided[linenum]
3743
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003744 # Block bodies should not be followed by a semicolon. Due to C++11
3745 # brace initialization, there are more places where semicolons are
3746 # required than not, so we use a whitelist approach to check these
3747 # rather than a blacklist. These are the places where "};" should
3748 # be replaced by just "}":
3749 # 1. Some flavor of block following closing parenthesis:
3750 # for (;;) {};
3751 # while (...) {};
3752 # switch (...) {};
3753 # Function(...) {};
3754 # if (...) {};
3755 # if (...) else if (...) {};
3756 #
3757 # 2. else block:
3758 # if (...) else {};
3759 #
3760 # 3. const member function:
3761 # Function(...) const {};
3762 #
3763 # 4. Block following some statement:
3764 # x = 42;
3765 # {};
3766 #
3767 # 5. Block at the beginning of a function:
3768 # Function(...) {
3769 # {};
3770 # }
3771 #
3772 # Note that naively checking for the preceding "{" will also match
3773 # braces inside multi-dimensional arrays, but this is fine since
3774 # that expression will not contain semicolons.
3775 #
3776 # 6. Block following another block:
3777 # while (true) {}
3778 # {};
3779 #
3780 # 7. End of namespaces:
3781 # namespace {};
3782 #
3783 # These semicolons seems far more common than other kinds of
3784 # redundant semicolons, possibly due to people converting classes
3785 # to namespaces. For now we do not warn for this case.
3786 #
3787 # Try matching case 1 first.
3788 match = Match(r'^(.*\)\s*)\{', line)
3789 if match:
3790 # Matched closing parenthesis (case 1). Check the token before the
3791 # matching opening parenthesis, and don't warn if it looks like a
3792 # macro. This avoids these false positives:
3793 # - macro that defines a base class
3794 # - multi-line macro that defines a base class
3795 # - macro that defines the whole class-head
3796 #
3797 # But we still issue warnings for macros that we know are safe to
3798 # warn, specifically:
3799 # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
3800 # - TYPED_TEST
3801 # - INTERFACE_DEF
3802 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
3803 #
3804 # We implement a whitelist of safe macros instead of a blacklist of
3805 # unsafe macros, even though the latter appears less frequently in
3806 # google code and would have been easier to implement. This is because
3807 # the downside for getting the whitelist wrong means some extra
3808 # semicolons, while the downside for getting the blacklist wrong
3809 # would result in compile errors.
3810 #
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003811 # In addition to macros, we also don't want to warn on
3812 # - Compound literals
3813 # - Lambdas
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003814 # - alignas specifier with anonymous structs
3815 # - decltype
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003816 closing_brace_pos = match.group(1).rfind(')')
3817 opening_parenthesis = ReverseCloseExpression(
3818 clean_lines, linenum, closing_brace_pos)
3819 if opening_parenthesis[2] > -1:
3820 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003821 macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003822 func = Match(r'^(.*\])\s*$', line_prefix)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003823 if ((macro and
3824 macro.group(1) not in (
3825 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
3826 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
3827 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003828 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003829 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003830 Search(r'\bdecltype$', line_prefix) or
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003831 Search(r'\s+=\s*$', line_prefix)):
3832 match = None
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003833 if (match and
3834 opening_parenthesis[1] > 1 and
3835 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
3836 # Multi-line lambda-expression
3837 match = None
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003838
3839 else:
3840 # Try matching cases 2-3.
3841 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
3842 if not match:
3843 # Try matching cases 4-6. These are always matched on separate lines.
3844 #
3845 # Note that we can't simply concatenate the previous line to the
3846 # current line and do a single match, otherwise we may output
3847 # duplicate warnings for the blank line case:
3848 # if (cond) {
3849 # // blank line
3850 # }
3851 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3852 if prevline and Search(r'[;{}]\s*$', prevline):
3853 match = Match(r'^(\s*)\{', line)
3854
3855 # Check matching closing brace
3856 if match:
3857 (endline, endlinenum, endpos) = CloseExpression(
3858 clean_lines, linenum, len(match.group(1)))
3859 if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
3860 # Current {} pair is eligible for semicolon check, and we have found
3861 # the redundant semicolon, output warning here.
3862 #
3863 # Note: because we are scanning forward for opening braces, and
3864 # outputting warnings for the matching closing brace, if there are
3865 # nested blocks with trailing semicolons, we will get the error
3866 # messages in reversed order.
3867 error(filename, endlinenum, 'readability/braces', 4,
3868 "You don't need a ; after a }")
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003869
3870
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003871def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
3872 """Look for empty loop/conditional body with only a single semicolon.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003873
3874 Args:
3875 filename: The name of the current file.
3876 clean_lines: A CleansedLines instance containing the file.
3877 linenum: The number of the line to check.
3878 error: The function to call with any errors found.
3879 """
3880
3881 # Search for loop keywords at the beginning of the line. Because only
3882 # whitespaces are allowed before the keywords, this will also ignore most
3883 # do-while-loops, since those lines should start with closing brace.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003884 #
3885 # We also check "if" blocks here, since an empty conditional block
3886 # is likely an error.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003887 line = clean_lines.elided[linenum]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003888 matched = Match(r'\s*(for|while|if)\s*\(', line)
3889 if matched:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003890 # Find the end of the conditional expression.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003891 (end_line, end_linenum, end_pos) = CloseExpression(
3892 clean_lines, linenum, line.find('('))
3893
3894 # Output warning if what follows the condition expression is a semicolon.
3895 # No warning for all other cases, including whitespace or newline, since we
3896 # have a separate check for semicolons preceded by whitespace.
3897 if end_pos >= 0 and Match(r';', end_line[end_pos:]):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003898 if matched.group(1) == 'if':
3899 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
3900 'Empty conditional bodies should use {}')
3901 else:
3902 error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
3903 'Empty loop bodies should use {} or continue')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003904
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003905 # Check for if statements that have completely empty bodies (no comments)
3906 # and no else clauses.
3907 if end_pos >= 0 and matched.group(1) == 'if':
3908 # Find the position of the opening { for the if statement.
3909 # Return without logging an error if it has no brackets.
3910 opening_linenum = end_linenum
3911 opening_line_fragment = end_line[end_pos:]
3912 # Loop until EOF or find anything that's not whitespace or opening {.
3913 while not Search(r'^\s*\{', opening_line_fragment):
3914 if Search(r'^(?!\s*$)', opening_line_fragment):
3915 # Conditional has no brackets.
3916 return
3917 opening_linenum += 1
3918 if opening_linenum == len(clean_lines.elided):
3919 # Couldn't find conditional's opening { or any code before EOF.
3920 return
3921 opening_line_fragment = clean_lines.elided[opening_linenum]
3922 # Set opening_line (opening_line_fragment may not be entire opening line).
3923 opening_line = clean_lines.elided[opening_linenum]
3924
3925 # Find the position of the closing }.
3926 opening_pos = opening_line_fragment.find('{')
3927 if opening_linenum == end_linenum:
3928 # We need to make opening_pos relative to the start of the entire line.
3929 opening_pos += end_pos
3930 (closing_line, closing_linenum, closing_pos) = CloseExpression(
3931 clean_lines, opening_linenum, opening_pos)
3932 if closing_pos < 0:
3933 return
3934
3935 # Now construct the body of the conditional. This consists of the portion
3936 # of the opening line after the {, all lines until the closing line,
3937 # and the portion of the closing line before the }.
3938 if (clean_lines.raw_lines[opening_linenum] !=
3939 CleanseComments(clean_lines.raw_lines[opening_linenum])):
3940 # Opening line ends with a comment, so conditional isn't empty.
3941 return
3942 if closing_linenum > opening_linenum:
3943 # Opening line after the {. Ignore comments here since we checked above.
3944 body = list(opening_line[opening_pos+1:])
3945 # All lines until closing line, excluding closing line, with comments.
3946 body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
3947 # Closing line before the }. Won't (and can't) have comments.
3948 body.append(clean_lines.elided[closing_linenum][:closing_pos-1])
3949 body = '\n'.join(body)
3950 else:
3951 # If statement has brackets and fits on a single line.
3952 body = opening_line[opening_pos+1:closing_pos-1]
3953
3954 # Check if the body is empty
3955 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
3956 return
3957 # The body is empty. Now make sure there's not an else clause.
3958 current_linenum = closing_linenum
3959 current_line_fragment = closing_line[closing_pos:]
3960 # Loop until EOF or find anything that's not whitespace or else clause.
3961 while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
3962 if Search(r'^(?=\s*else)', current_line_fragment):
3963 # Found an else clause, so don't log an error.
3964 return
3965 current_linenum += 1
3966 if current_linenum == len(clean_lines.elided):
3967 break
3968 current_line_fragment = clean_lines.elided[current_linenum]
3969
3970 # The body is empty and there's no else clause until EOF or other code.
3971 error(filename, end_linenum, 'whitespace/empty_if_body', 4,
3972 ('If statement had no body and no else clause'))
3973
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003974
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003975def FindCheckMacro(line):
3976 """Find a replaceable CHECK-like macro.
3977
3978 Args:
3979 line: line to search on.
3980 Returns:
3981 (macro name, start position), or (None, -1) if no replaceable
3982 macro is found.
3983 """
3984 for macro in _CHECK_MACROS:
3985 i = line.find(macro)
3986 if i >= 0:
3987 # Find opening parenthesis. Do a regular expression match here
3988 # to make sure that we are matching the expected CHECK macro, as
3989 # opposed to some other macro that happens to contain the CHECK
3990 # substring.
3991 matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
3992 if not matched:
3993 continue
3994 return (macro, len(matched.group(1)))
3995 return (None, -1)
3996
3997
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003998def CheckCheck(filename, clean_lines, linenum, error):
3999 """Checks the use of CHECK and EXPECT macros.
4000
4001 Args:
4002 filename: The name of the current file.
4003 clean_lines: A CleansedLines instance containing the file.
4004 linenum: The number of the line to check.
4005 error: The function to call with any errors found.
4006 """
4007
4008 # Decide the set of replacement macros that should be suggested
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004009 lines = clean_lines.elided
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004010 (check_macro, start_pos) = FindCheckMacro(lines[linenum])
4011 if not check_macro:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004012 return
4013
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004014 # Find end of the boolean expression by matching parentheses
4015 (last_line, end_line, end_pos) = CloseExpression(
4016 clean_lines, linenum, start_pos)
4017 if end_pos < 0:
4018 return
avakulenko@google.com59146752014-08-11 20:20:55 +00004019
4020 # If the check macro is followed by something other than a
4021 # semicolon, assume users will log their own custom error messages
4022 # and don't suggest any replacements.
4023 if not Match(r'\s*;', last_line[end_pos:]):
4024 return
4025
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004026 if linenum == end_line:
4027 expression = lines[linenum][start_pos + 1:end_pos - 1]
4028 else:
4029 expression = lines[linenum][start_pos + 1:]
4030 for i in xrange(linenum + 1, end_line):
4031 expression += lines[i]
4032 expression += last_line[0:end_pos - 1]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004033
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004034 # Parse expression so that we can take parentheses into account.
4035 # This avoids false positives for inputs like "CHECK((a < 4) == b)",
4036 # which is not replaceable by CHECK_LE.
4037 lhs = ''
4038 rhs = ''
4039 operator = None
4040 while expression:
4041 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
4042 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4043 if matched:
4044 token = matched.group(1)
4045 if token == '(':
4046 # Parenthesized operand
4047 expression = matched.group(2)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004048 (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004049 if end < 0:
4050 return # Unmatched parenthesis
4051 lhs += '(' + expression[0:end]
4052 expression = expression[end:]
4053 elif token in ('&&', '||'):
4054 # Logical and/or operators. This means the expression
4055 # contains more than one term, for example:
4056 # CHECK(42 < a && a < b);
4057 #
4058 # These are not replaceable with CHECK_LE, so bail out early.
4059 return
4060 elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
4061 # Non-relational operator
4062 lhs += token
4063 expression = matched.group(2)
4064 else:
4065 # Relational operator
4066 operator = token
4067 rhs = matched.group(2)
4068 break
4069 else:
4070 # Unparenthesized operand. Instead of appending to lhs one character
4071 # at a time, we do another regular expression match to consume several
4072 # characters at once if possible. Trivial benchmark shows that this
4073 # is more efficient when the operands are longer than a single
4074 # character, which is generally the case.
4075 matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
4076 if not matched:
4077 matched = Match(r'^(\s*\S)(.*)$', expression)
4078 if not matched:
4079 break
4080 lhs += matched.group(1)
4081 expression = matched.group(2)
4082
4083 # Only apply checks if we got all parts of the boolean expression
4084 if not (lhs and operator and rhs):
4085 return
4086
4087 # Check that rhs do not contain logical operators. We already know
4088 # that lhs is fine since the loop above parses out && and ||.
4089 if rhs.find('&&') > -1 or rhs.find('||') > -1:
4090 return
4091
4092 # At least one of the operands must be a constant literal. This is
4093 # to avoid suggesting replacements for unprintable things like
4094 # CHECK(variable != iterator)
4095 #
4096 # The following pattern matches decimal, hex integers, strings, and
4097 # characters (in that order).
4098 lhs = lhs.strip()
4099 rhs = rhs.strip()
4100 match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
4101 if Match(match_constant, lhs) or Match(match_constant, rhs):
4102 # Note: since we know both lhs and rhs, we can provide a more
4103 # descriptive error message like:
4104 # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
4105 # Instead of:
4106 # Consider using CHECK_EQ instead of CHECK(a == b)
4107 #
4108 # We are still keeping the less descriptive message because if lhs
4109 # or rhs gets long, the error message might become unreadable.
4110 error(filename, linenum, 'readability/check', 2,
4111 'Consider using %s instead of %s(a %s b)' % (
4112 _CHECK_REPLACEMENT[check_macro][operator],
4113 check_macro, operator))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004114
4115
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004116def CheckAltTokens(filename, clean_lines, linenum, error):
4117 """Check alternative keywords being used in boolean expressions.
4118
4119 Args:
4120 filename: The name of the current file.
4121 clean_lines: A CleansedLines instance containing the file.
4122 linenum: The number of the line to check.
4123 error: The function to call with any errors found.
4124 """
4125 line = clean_lines.elided[linenum]
4126
4127 # Avoid preprocessor lines
4128 if Match(r'^\s*#', line):
4129 return
4130
4131 # Last ditch effort to avoid multi-line comments. This will not help
4132 # if the comment started before the current line or ended after the
4133 # current line, but it catches most of the false positives. At least,
4134 # it provides a way to workaround this warning for people who use
4135 # multi-line comments in preprocessor macros.
4136 #
4137 # TODO(unknown): remove this once cpplint has better support for
4138 # multi-line comments.
4139 if line.find('/*') >= 0 or line.find('*/') >= 0:
4140 return
4141
4142 for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4143 error(filename, linenum, 'readability/alt_tokens', 2,
4144 'Use operator %s instead of %s' % (
4145 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4146
4147
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004148def GetLineWidth(line):
4149 """Determines the width of the line in column positions.
4150
4151 Args:
4152 line: A string, which may be a Unicode string.
4153
4154 Returns:
4155 The width of the line in column positions, accounting for Unicode
4156 combining characters and wide characters.
4157 """
4158 if isinstance(line, unicode):
4159 width = 0
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004160 for uc in unicodedata.normalize('NFC', line):
4161 if unicodedata.east_asian_width(uc) in ('W', 'F'):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004162 width += 2
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004163 elif not unicodedata.combining(uc):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004164 width += 1
4165 return width
4166 else:
4167 return len(line)
4168
4169
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004170def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004171 error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004172 """Checks rules from the 'C++ style rules' section of cppguide.html.
4173
4174 Most of these rules are hard to test (naming, comment style), but we
4175 do what we can. In particular we check for 2-space indents, line lengths,
4176 tab usage, spaces inside code, etc.
4177
4178 Args:
4179 filename: The name of the current file.
4180 clean_lines: A CleansedLines instance containing the file.
4181 linenum: The number of the line to check.
4182 file_extension: The extension (without the dot) of the filename.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004183 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004184 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004185 error: The function to call with any errors found.
4186 """
4187
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004188 # Don't use "elided" lines here, otherwise we can't check commented lines.
4189 # Don't want to use "raw" either, because we don't want to check inside C++11
4190 # raw strings,
4191 raw_lines = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004192 line = raw_lines[linenum]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004193 prev = raw_lines[linenum - 1] if linenum > 0 else ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004194
4195 if line.find('\t') != -1:
4196 error(filename, linenum, 'whitespace/tab', 1,
4197 'Tab found; better to use spaces')
4198
4199 # One or three blank spaces at the beginning of the line is weird; it's
4200 # hard to reconcile that with 2-space indents.
4201 # NOTE: here are the conditions rob pike used for his tests. Mine aren't
4202 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
4203 # if(RLENGTH > 20) complain = 0;
4204 # if(match($0, " +(error|private|public|protected):")) complain = 0;
4205 # if(match(prev, "&& *$")) complain = 0;
4206 # if(match(prev, "\\|\\| *$")) complain = 0;
4207 # if(match(prev, "[\",=><] *$")) complain = 0;
4208 # if(match($0, " <<")) complain = 0;
4209 # if(match(prev, " +for \\(")) complain = 0;
4210 # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004211 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
4212 classinfo = nesting_state.InnermostClass()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004213 initial_spaces = 0
4214 cleansed_line = clean_lines.elided[linenum]
4215 while initial_spaces < len(line) and line[initial_spaces] == ' ':
4216 initial_spaces += 1
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004217 # There are certain situations we allow one space, notably for
4218 # section labels, and also lines containing multi-line raw strings.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004219 # We also don't check for lines that look like continuation lines
4220 # (of lines ending in double quotes, commas, equals, or angle brackets)
4221 # because the rules for how to indent those are non-trivial.
4222 if (not Search(r'[",=><] *$', prev) and
4223 (initial_spaces == 1 or initial_spaces == 3) and
4224 not Match(scope_or_label_pattern, cleansed_line) and
4225 not (clean_lines.raw_lines[linenum] != line and
4226 Match(r'^\s*""', line))):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004227 error(filename, linenum, 'whitespace/indent', 3,
4228 'Weird number of spaces at line-start. '
4229 'Are you using a 2-space indent?')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004230
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004231 if line and line[-1].isspace():
4232 error(filename, linenum, 'whitespace/end_of_line', 4,
4233 'Line ends in whitespace. Consider deleting these extra spaces.')
4234
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004235 # Check if the line is a header guard.
4236 is_header_guard = False
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00004237 if file_extension == 'h':
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004238 cppvar = GetHeaderGuardCPPVariable(filename)
4239 if (line.startswith('#ifndef %s' % cppvar) or
4240 line.startswith('#define %s' % cppvar) or
4241 line.startswith('#endif // %s' % cppvar)):
4242 is_header_guard = True
4243 # #include lines and header guards can be long, since there's no clean way to
4244 # split them.
erg@google.com6317a9c2009-06-25 00:28:19 +00004245 #
4246 # URLs can be long too. It's possible to split these, but it makes them
4247 # harder to cut&paste.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004248 #
4249 # The "$Id:...$" comment may also get very long without it being the
4250 # developers fault.
erg@google.com6317a9c2009-06-25 00:28:19 +00004251 if (not line.startswith('#include') and not is_header_guard and
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004252 not Match(r'^\s*//.*http(s?)://\S*$', line) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004253 not Match(r'^\s*//\s*[^\s]*$', line) and
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004254 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004255 line_width = GetLineWidth(line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004256 if line_width > _line_length:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004257 error(filename, linenum, 'whitespace/line_length', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004258 'Lines should be <= %i characters long' % _line_length)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004259
4260 if (cleansed_line.count(';') > 1 and
4261 # for loops are allowed two ;'s (and may run over two lines).
4262 cleansed_line.find('for') == -1 and
4263 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
4264 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
4265 # It's ok to have many commands in a switch case that fits in 1 line
4266 not ((cleansed_line.find('case ') != -1 or
4267 cleansed_line.find('default:') != -1) and
4268 cleansed_line.find('break;') != -1)):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004269 error(filename, linenum, 'whitespace/newline', 0,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004270 'More than one command on the same line')
4271
4272 # Some more style checks
4273 CheckBraces(filename, clean_lines, linenum, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004274 CheckTrailingSemicolon(filename, clean_lines, linenum, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004275 CheckEmptyBlockBody(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004276 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004277 CheckOperatorSpacing(filename, clean_lines, linenum, error)
4278 CheckParenthesisSpacing(filename, clean_lines, linenum, error)
4279 CheckCommaSpacing(filename, clean_lines, linenum, error)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004280 CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004281 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004282 CheckCheck(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004283 CheckAltTokens(filename, clean_lines, linenum, error)
4284 classinfo = nesting_state.InnermostClass()
4285 if classinfo:
4286 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004287
4288
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004289_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4290# Matches the first component of a filename delimited by -s and _s. That is:
4291# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
4292# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
4293# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
4294# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
4295_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
4296
4297
4298def _DropCommonSuffixes(filename):
4299 """Drops common suffixes like _test.cc or -inl.h from filename.
4300
4301 For example:
4302 >>> _DropCommonSuffixes('foo/foo-inl.h')
4303 'foo/foo'
4304 >>> _DropCommonSuffixes('foo/bar/foo.cc')
4305 'foo/bar/foo'
4306 >>> _DropCommonSuffixes('foo/foo_internal.h')
4307 'foo/foo'
4308 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
4309 'foo/foo_unusualinternal'
4310
4311 Args:
4312 filename: The input filename.
4313
4314 Returns:
4315 The filename with the common suffix removed.
4316 """
4317 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
4318 'inl.h', 'impl.h', 'internal.h'):
4319 if (filename.endswith(suffix) and len(filename) > len(suffix) and
4320 filename[-len(suffix) - 1] in ('-', '_')):
4321 return filename[:-len(suffix) - 1]
4322 return os.path.splitext(filename)[0]
4323
4324
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004325def _ClassifyInclude(fileinfo, include, is_system):
4326 """Figures out what kind of header 'include' is.
4327
4328 Args:
4329 fileinfo: The current file cpplint is running over. A FileInfo instance.
4330 include: The path to a #included file.
4331 is_system: True if the #include used <> rather than "".
4332
4333 Returns:
4334 One of the _XXX_HEADER constants.
4335
4336 For example:
4337 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
4338 _C_SYS_HEADER
4339 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
4340 _CPP_SYS_HEADER
4341 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
4342 _LIKELY_MY_HEADER
4343 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
4344 ... 'bar/foo_other_ext.h', False)
4345 _POSSIBLE_MY_HEADER
4346 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
4347 _OTHER_HEADER
4348 """
4349 # This is a list of all standard c++ header files, except
4350 # those already checked for above.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004351 is_cpp_h = include in _CPP_HEADERS
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004352
4353 if is_system:
4354 if is_cpp_h:
4355 return _CPP_SYS_HEADER
4356 else:
4357 return _C_SYS_HEADER
4358
4359 # If the target file and the include we're checking share a
4360 # basename when we drop common extensions, and the include
4361 # lives in . , then it's likely to be owned by the target file.
4362 target_dir, target_base = (
4363 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
4364 include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
4365 if target_base == include_base and (
4366 include_dir == target_dir or
4367 include_dir == os.path.normpath(target_dir + '/../public')):
4368 return _LIKELY_MY_HEADER
4369
4370 # If the target and include share some initial basename
4371 # component, it's possible the target is implementing the
4372 # include, so it's allowed to be first, but we'll never
4373 # complain if it's not there.
4374 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4375 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4376 if (target_first_component and include_first_component and
4377 target_first_component.group(0) ==
4378 include_first_component.group(0)):
4379 return _POSSIBLE_MY_HEADER
4380
4381 return _OTHER_HEADER
4382
4383
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004384
erg@google.com6317a9c2009-06-25 00:28:19 +00004385def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
4386 """Check rules that are applicable to #include lines.
4387
4388 Strings on #include lines are NOT removed from elided line, to make
4389 certain tasks easier. However, to prevent false positives, checks
4390 applicable to #include lines in CheckLanguage must be put here.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004391
4392 Args:
4393 filename: The name of the current file.
4394 clean_lines: A CleansedLines instance containing the file.
4395 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004396 include_state: An _IncludeState instance in which the headers are inserted.
4397 error: The function to call with any errors found.
4398 """
4399 fileinfo = FileInfo(filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00004400 line = clean_lines.lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004401
4402 # "include" should use the new style "foo/bar.h" instead of just "bar.h"
avakulenko@google.com59146752014-08-11 20:20:55 +00004403 # Only do this check if the included header follows google naming
4404 # conventions. If not, assume that it's a 3rd party API that
4405 # requires special include conventions.
4406 #
4407 # We also make an exception for Lua headers, which follow google
4408 # naming convention but not the include convention.
4409 match = Match(r'#include\s*"([^/]+\.h)"', line)
4410 if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004411 error(filename, linenum, 'build/include', 4,
4412 'Include the directory when naming .h files')
4413
4414 # we shouldn't include a file more than once. actually, there are a
4415 # handful of instances where doing so is okay, but in general it's
4416 # not.
erg@google.com6317a9c2009-06-25 00:28:19 +00004417 match = _RE_PATTERN_INCLUDE.search(line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004418 if match:
4419 include = match.group(2)
4420 is_system = (match.group(1) == '<')
avakulenko@google.com59146752014-08-11 20:20:55 +00004421 duplicate_line = include_state.FindHeader(include)
4422 if duplicate_line >= 0:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004423 error(filename, linenum, 'build/include', 4,
4424 '"%s" already included at %s:%s' %
avakulenko@google.com59146752014-08-11 20:20:55 +00004425 (include, filename, duplicate_line))
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004426 elif (include.endswith('.cc') and
4427 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4428 error(filename, linenum, 'build/include', 4,
4429 'Do not include .cc files from other packages')
avakulenko@google.com59146752014-08-11 20:20:55 +00004430 elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4431 include_state.include_list[-1].append((include, linenum))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004432
4433 # We want to ensure that headers appear in the right order:
4434 # 1) for foo.cc, foo.h (preferred location)
4435 # 2) c system files
4436 # 3) cpp system files
4437 # 4) for foo.cc, foo.h (deprecated location)
4438 # 5) other google headers
4439 #
4440 # We classify each include statement as one of those 5 types
4441 # using a number of techniques. The include_state object keeps
4442 # track of the highest type seen, and complains if we see a
4443 # lower type after that.
4444 error_message = include_state.CheckNextIncludeOrder(
4445 _ClassifyInclude(fileinfo, include, is_system))
4446 if error_message:
4447 error(filename, linenum, 'build/include_order', 4,
4448 '%s. Should be: %s.h, c system, c++ system, other.' %
4449 (error_message, fileinfo.BaseName()))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004450 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4451 if not include_state.IsInAlphabeticalOrder(
4452 clean_lines, linenum, canonical_include):
erg@google.com26970fa2009-11-17 18:07:32 +00004453 error(filename, linenum, 'build/include_alpha', 4,
4454 'Include "%s" not in alphabetical order' % include)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004455 include_state.SetLastHeader(canonical_include)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004456
erg@google.com6317a9c2009-06-25 00:28:19 +00004457
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004458
4459def _GetTextInside(text, start_pattern):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004460 r"""Retrieves all the text between matching open and close parentheses.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004461
4462 Given a string of lines and a regular expression string, retrieve all the text
4463 following the expression and between opening punctuation symbols like
4464 (, [, or {, and the matching close-punctuation symbol. This properly nested
4465 occurrences of the punctuations, so for the text like
4466 printf(a(), b(c()));
4467 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
4468 start_pattern must match string having an open punctuation symbol at the end.
4469
4470 Args:
4471 text: The lines to extract text. Its comments and strings must be elided.
4472 It can be single line and can span multiple lines.
4473 start_pattern: The regexp string indicating where to start extracting
4474 the text.
4475 Returns:
4476 The extracted text.
4477 None if either the opening string or ending punctuation could not be found.
4478 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004479 # TODO(unknown): Audit cpplint.py to see what places could be profitably
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004480 # rewritten to use _GetTextInside (and use inferior regexp matching today).
4481
4482 # Give opening punctuations to get the matching close-punctuations.
4483 matching_punctuation = {'(': ')', '{': '}', '[': ']'}
4484 closing_punctuation = set(matching_punctuation.itervalues())
4485
4486 # Find the position to start extracting text.
4487 match = re.search(start_pattern, text, re.M)
4488 if not match: # start_pattern not found in text.
4489 return None
4490 start_position = match.end(0)
4491
4492 assert start_position > 0, (
4493 'start_pattern must ends with an opening punctuation.')
4494 assert text[start_position - 1] in matching_punctuation, (
4495 'start_pattern must ends with an opening punctuation.')
4496 # Stack of closing punctuations we expect to have in text after position.
4497 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4498 position = start_position
4499 while punctuation_stack and position < len(text):
4500 if text[position] == punctuation_stack[-1]:
4501 punctuation_stack.pop()
4502 elif text[position] in closing_punctuation:
4503 # A closing punctuation without matching opening punctuations.
4504 return None
4505 elif text[position] in matching_punctuation:
4506 punctuation_stack.append(matching_punctuation[text[position]])
4507 position += 1
4508 if punctuation_stack:
4509 # Opening punctuations left without matching close-punctuations.
4510 return None
4511 # punctuations match.
4512 return text[start_position:position - 1]
4513
4514
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004515# Patterns for matching call-by-reference parameters.
4516#
4517# Supports nested templates up to 2 levels deep using this messy pattern:
4518# < (?: < (?: < [^<>]*
4519# >
4520# | [^<>] )*
4521# >
4522# | [^<>] )*
4523# >
4524_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
4525_RE_PATTERN_TYPE = (
4526 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
4527 r'(?:\w|'
4528 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
4529 r'::)+')
4530# A call-by-reference parameter ends with '& identifier'.
4531_RE_PATTERN_REF_PARAM = re.compile(
4532 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
4533 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
4534# A call-by-const-reference parameter either ends with 'const& identifier'
4535# or looks like 'const type& identifier' when 'type' is atomic.
4536_RE_PATTERN_CONST_REF_PARAM = (
4537 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4538 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004539# Stream types.
4540_RE_PATTERN_REF_STREAM_PARAM = (
4541 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004542
4543
4544def CheckLanguage(filename, clean_lines, linenum, file_extension,
4545 include_state, nesting_state, error):
erg@google.com6317a9c2009-06-25 00:28:19 +00004546 """Checks rules from the 'C++ language rules' section of cppguide.html.
4547
4548 Some of these rules are hard to test (function overloading, using
4549 uint32 inappropriately), but we do the best we can.
4550
4551 Args:
4552 filename: The name of the current file.
4553 clean_lines: A CleansedLines instance containing the file.
4554 linenum: The number of the line to check.
4555 file_extension: The extension (without the dot) of the filename.
4556 include_state: An _IncludeState instance in which the headers are inserted.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004557 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004558 the current stack of nested blocks being parsed.
erg@google.com6317a9c2009-06-25 00:28:19 +00004559 error: The function to call with any errors found.
4560 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004561 # If the line is empty or consists of entirely a comment, no need to
4562 # check it.
4563 line = clean_lines.elided[linenum]
4564 if not line:
4565 return
4566
erg@google.com6317a9c2009-06-25 00:28:19 +00004567 match = _RE_PATTERN_INCLUDE.search(line)
4568 if match:
4569 CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
4570 return
4571
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004572 # Reset include state across preprocessor directives. This is meant
4573 # to silence warnings for conditional includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00004574 match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4575 if match:
4576 include_state.ResetSection(match.group(1))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004577
4578 # Make Windows paths like Unix.
4579 fullname = os.path.abspath(filename).replace('\\', '/')
skym@chromium.org3990c412016-02-05 20:55:12 +00004580
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004581 # Perform other checks now that we are sure that this is not an include line
4582 CheckCasts(filename, clean_lines, linenum, error)
4583 CheckGlobalStatic(filename, clean_lines, linenum, error)
4584 CheckPrintf(filename, clean_lines, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004585
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00004586 if file_extension == 'h':
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004587 # TODO(unknown): check that 1-arg constructors are explicit.
4588 # How to tell it's a constructor?
4589 # (handled in CheckForNonStandardConstructs for now)
avakulenko@google.com59146752014-08-11 20:20:55 +00004590 # TODO(unknown): check that classes declare or disable copy/assign
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004591 # (level 1 error)
4592 pass
4593
4594 # Check if people are using the verboten C basic types. The only exception
4595 # we regularly allow is "unsigned short port" for port.
4596 if Search(r'\bshort port\b', line):
4597 if not Search(r'\bunsigned short port\b', line):
4598 error(filename, linenum, 'runtime/int', 4,
4599 'Use "unsigned short" for ports, not "short"')
4600 else:
4601 match = Search(r'\b(short|long(?! +double)|long long)\b', line)
4602 if match:
4603 error(filename, linenum, 'runtime/int', 4,
4604 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4605
erg@google.com26970fa2009-11-17 18:07:32 +00004606 # Check if some verboten operator overloading is going on
4607 # TODO(unknown): catch out-of-line unary operator&:
4608 # class X {};
4609 # int operator&(const X& x) { return 42; } // unary operator&
4610 # The trick is it's hard to tell apart from binary operator&:
4611 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
4612 if Search(r'\boperator\s*&\s*\(\s*\)', line):
4613 error(filename, linenum, 'runtime/operator', 4,
4614 'Unary operator& is dangerous. Do not use it.')
4615
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004616 # Check for suspicious usage of "if" like
4617 # } if (a == b) {
4618 if Search(r'\}\s*if\s*\(', line):
4619 error(filename, linenum, 'readability/braces', 4,
4620 'Did you mean "else if"? If not, start a new line for "if".')
4621
4622 # Check for potential format string bugs like printf(foo).
4623 # We constrain the pattern not to pick things like DocidForPrintf(foo).
4624 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004625 # TODO(unknown): Catch the following case. Need to change the calling
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004626 # convention of the whole function to process multiple line to handle it.
4627 # printf(
4628 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
4629 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
4630 if printf_args:
4631 match = Match(r'([\w.\->()]+)$', printf_args)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004632 if match and match.group(1) != '__VA_ARGS__':
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004633 function_name = re.search(r'\b((?:string)?printf)\s*\(',
4634 line, re.I).group(1)
4635 error(filename, linenum, 'runtime/printf', 4,
4636 'Potential format string bug. Do %s("%%s", %s) instead.'
4637 % (function_name, match.group(1)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004638
4639 # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
4640 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4641 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4642 error(filename, linenum, 'runtime/memset', 4,
4643 'Did you mean "memset(%s, 0, %s)"?'
4644 % (match.group(1), match.group(2)))
4645
4646 if Search(r'\busing namespace\b', line):
4647 error(filename, linenum, 'build/namespaces', 5,
4648 'Do not use namespace using-directives. '
4649 'Use using-declarations instead.')
4650
4651 # Detect variable-length arrays.
4652 match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4653 if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
4654 match.group(3).find(']') == -1):
4655 # Split the size using space and arithmetic operators as delimiters.
4656 # If any of the resulting tokens are not compile time constants then
4657 # report the error.
4658 tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4659 is_const = True
4660 skip_next = False
4661 for tok in tokens:
4662 if skip_next:
4663 skip_next = False
4664 continue
4665
4666 if Search(r'sizeof\(.+\)', tok): continue
4667 if Search(r'arraysize\(\w+\)', tok): continue
Avi Drissman4157ba12019-01-09 14:18:07 +00004668 if Search(r'base::size\(.+\)', tok): continue
4669 if Search(r'std::size\(.+\)', tok): continue
4670 if Search(r'std::extent<.+>', tok): continue
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004671
4672 tok = tok.lstrip('(')
4673 tok = tok.rstrip(')')
4674 if not tok: continue
4675 if Match(r'\d+', tok): continue
4676 if Match(r'0[xX][0-9a-fA-F]+', tok): continue
4677 if Match(r'k[A-Z0-9]\w*', tok): continue
4678 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
4679 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
4680 # A catch all for tricky sizeof cases, including 'sizeof expression',
4681 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004682 # requires skipping the next token because we split on ' ' and '*'.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004683 if tok.startswith('sizeof'):
4684 skip_next = True
4685 continue
4686 is_const = False
4687 break
4688 if not is_const:
4689 error(filename, linenum, 'runtime/arrays', 1,
4690 'Do not use variable-length arrays. Use an appropriately named '
4691 "('k' followed by CamelCase) compile-time constant for the size.")
4692
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004693 # Check for use of unnamed namespaces in header files. Registration
4694 # macros are typically OK, so we allow use of "namespace {" on lines
4695 # that end with backslashes.
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00004696 if (file_extension == 'h'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004697 and Search(r'\bnamespace\s*{', line)
4698 and line[-1] != '\\'):
4699 error(filename, linenum, 'build/namespaces', 4,
4700 'Do not use unnamed namespaces in header files. See '
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00004701 'https://google.github.io/styleguide/cppguide.html#Namespaces'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004702 ' for more information.')
4703
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004704
4705def CheckGlobalStatic(filename, clean_lines, linenum, error):
4706 """Check for unsafe global or static objects.
4707
4708 Args:
4709 filename: The name of the current file.
4710 clean_lines: A CleansedLines instance containing the file.
4711 linenum: The number of the line to check.
4712 error: The function to call with any errors found.
4713 """
4714 line = clean_lines.elided[linenum]
4715
avakulenko@google.com59146752014-08-11 20:20:55 +00004716 # Match two lines at a time to support multiline declarations
4717 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
4718 line += clean_lines.elided[linenum + 1].strip()
4719
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004720 # Check for people declaring static/global STL strings at the top level.
4721 # This is dangerous because the C++ language does not guarantee that
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004722 # globals with constructors are initialized before the first access, and
4723 # also because globals can be destroyed when some threads are still running.
4724 # TODO(unknown): Generalize this to also find static unique_ptr instances.
4725 # TODO(unknown): File bugs for clang-tidy to find these.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004726 match = Match(
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004727 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
4728 r'([a-zA-Z0-9_:]+)\b(.*)',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004729 line)
avakulenko@google.com59146752014-08-11 20:20:55 +00004730
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004731 # Remove false positives:
4732 # - String pointers (as opposed to values).
4733 # string *pointer
4734 # const string *pointer
4735 # string const *pointer
4736 # string *const pointer
4737 #
4738 # - Functions and template specializations.
4739 # string Function<Type>(...
4740 # string Class<Type>::Method(...
4741 #
4742 # - Operators. These are matched separately because operator names
4743 # cross non-word boundaries, and trying to match both operators
4744 # and functions at the same time would decrease accuracy of
4745 # matching identifiers.
4746 # string Class::operator*()
4747 if (match and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004748 not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004749 not Search(r'\boperator\W', line) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004750 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
4751 if Search(r'\bconst\b', line):
4752 error(filename, linenum, 'runtime/string', 4,
4753 'For a static/global string constant, use a C style string '
4754 'instead: "%schar%s %s[]".' %
4755 (match.group(1), match.group(2) or '', match.group(3)))
4756 else:
4757 error(filename, linenum, 'runtime/string', 4,
4758 'Static/global string variables are not permitted.')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004759
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004760 if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
4761 Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004762 error(filename, linenum, 'runtime/init', 4,
4763 'You seem to be initializing a member variable with itself.')
4764
4765
4766def CheckPrintf(filename, clean_lines, linenum, error):
4767 """Check for printf related issues.
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 error: The function to call with any errors found.
4774 """
4775 line = clean_lines.elided[linenum]
4776
4777 # When snprintf is used, the second argument shouldn't be a literal.
4778 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
4779 if match and match.group(2) != '0':
4780 # If 2nd arg is zero, snprintf is used to calculate size.
4781 error(filename, linenum, 'runtime/printf', 3,
4782 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
4783 'to snprintf.' % (match.group(1), match.group(2)))
4784
4785 # Check if some verboten C functions are being used.
avakulenko@google.com59146752014-08-11 20:20:55 +00004786 if Search(r'\bsprintf\s*\(', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004787 error(filename, linenum, 'runtime/printf', 5,
4788 'Never use sprintf. Use snprintf instead.')
avakulenko@google.com59146752014-08-11 20:20:55 +00004789 match = Search(r'\b(strcpy|strcat)\s*\(', line)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004790 if match:
4791 error(filename, linenum, 'runtime/printf', 4,
4792 'Almost always, snprintf is better than %s' % match.group(1))
4793
4794
4795def IsDerivedFunction(clean_lines, linenum):
4796 """Check if current line contains an inherited function.
4797
4798 Args:
4799 clean_lines: A CleansedLines instance containing the file.
4800 linenum: The number of the line to check.
4801 Returns:
4802 True if current line contains a function with "override"
4803 virt-specifier.
4804 """
avakulenko@google.com59146752014-08-11 20:20:55 +00004805 # Scan back a few lines for start of current function
4806 for i in xrange(linenum, max(-1, linenum - 10), -1):
4807 match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
4808 if match:
4809 # Look for "override" after the matching closing parenthesis
4810 line, _, closing_paren = CloseExpression(
4811 clean_lines, i, len(match.group(1)))
4812 return (closing_paren >= 0 and
4813 Search(r'\boverride\b', line[closing_paren:]))
4814 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004815
4816
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004817def IsOutOfLineMethodDefinition(clean_lines, linenum):
4818 """Check if current line contains an out-of-line method definition.
4819
4820 Args:
4821 clean_lines: A CleansedLines instance containing the file.
4822 linenum: The number of the line to check.
4823 Returns:
4824 True if current line contains an out-of-line method definition.
4825 """
4826 # Scan back a few lines for start of current function
4827 for i in xrange(linenum, max(-1, linenum - 10), -1):
4828 if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
4829 return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
4830 return False
4831
4832
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004833def IsInitializerList(clean_lines, linenum):
4834 """Check if current line is inside constructor initializer list.
4835
4836 Args:
4837 clean_lines: A CleansedLines instance containing the file.
4838 linenum: The number of the line to check.
4839 Returns:
4840 True if current line appears to be inside constructor initializer
4841 list, False otherwise.
4842 """
4843 for i in xrange(linenum, 1, -1):
4844 line = clean_lines.elided[i]
4845 if i == linenum:
4846 remove_function_body = Match(r'^(.*)\{\s*$', line)
4847 if remove_function_body:
4848 line = remove_function_body.group(1)
4849
4850 if Search(r'\s:\s*\w+[({]', line):
4851 # A lone colon tend to indicate the start of a constructor
4852 # initializer list. It could also be a ternary operator, which
4853 # also tend to appear in constructor initializer lists as
4854 # opposed to parameter lists.
4855 return True
4856 if Search(r'\}\s*,\s*$', line):
4857 # A closing brace followed by a comma is probably the end of a
4858 # brace-initialized member in constructor initializer list.
4859 return True
4860 if Search(r'[{};]\s*$', line):
4861 # Found one of the following:
4862 # - A closing brace or semicolon, probably the end of the previous
4863 # function.
4864 # - An opening brace, probably the start of current class or namespace.
4865 #
4866 # Current line is probably not inside an initializer list since
4867 # we saw one of those things without seeing the starting colon.
4868 return False
4869
4870 # Got to the beginning of the file without seeing the start of
4871 # constructor initializer list.
4872 return False
4873
4874
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004875def CheckForNonConstReference(filename, clean_lines, linenum,
4876 nesting_state, error):
4877 """Check for non-const references.
4878
4879 Separate from CheckLanguage since it scans backwards from current
4880 line, instead of scanning forward.
4881
4882 Args:
4883 filename: The name of the current file.
4884 clean_lines: A CleansedLines instance containing the file.
4885 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004886 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004887 the current stack of nested blocks being parsed.
4888 error: The function to call with any errors found.
4889 """
4890 # Do nothing if there is no '&' on current line.
4891 line = clean_lines.elided[linenum]
4892 if '&' not in line:
4893 return
4894
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004895 # If a function is inherited, current function doesn't have much of
4896 # a choice, so any non-const references should not be blamed on
4897 # derived function.
4898 if IsDerivedFunction(clean_lines, linenum):
4899 return
4900
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004901 # Don't warn on out-of-line method definitions, as we would warn on the
4902 # in-line declaration, if it isn't marked with 'override'.
4903 if IsOutOfLineMethodDefinition(clean_lines, linenum):
4904 return
4905
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004906 # Long type names may be broken across multiple lines, usually in one
4907 # of these forms:
4908 # LongType
4909 # ::LongTypeContinued &identifier
4910 # LongType::
4911 # LongTypeContinued &identifier
4912 # LongType<
4913 # ...>::LongTypeContinued &identifier
4914 #
4915 # If we detected a type split across two lines, join the previous
4916 # line to current line so that we can match const references
4917 # accordingly.
4918 #
4919 # Note that this only scans back one line, since scanning back
4920 # arbitrary number of lines would be expensive. If you have a type
4921 # that spans more than 2 lines, please use a typedef.
4922 if linenum > 1:
4923 previous = None
4924 if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
4925 # previous_line\n + ::current_line
4926 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
4927 clean_lines.elided[linenum - 1])
4928 elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
4929 # previous_line::\n + current_line
4930 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
4931 clean_lines.elided[linenum - 1])
4932 if previous:
4933 line = previous.group(1) + line.lstrip()
4934 else:
4935 # Check for templated parameter that is split across multiple lines
4936 endpos = line.rfind('>')
4937 if endpos > -1:
4938 (_, startline, startpos) = ReverseCloseExpression(
4939 clean_lines, linenum, endpos)
4940 if startpos > -1 and startline < linenum:
4941 # Found the matching < on an earlier line, collect all
4942 # pieces up to current line.
4943 line = ''
4944 for i in xrange(startline, linenum + 1):
4945 line += clean_lines.elided[i].strip()
4946
4947 # Check for non-const references in function parameters. A single '&' may
4948 # found in the following places:
4949 # inside expression: binary & for bitwise AND
4950 # inside expression: unary & for taking the address of something
4951 # inside declarators: reference parameter
4952 # We will exclude the first two cases by checking that we are not inside a
4953 # function body, including one that was just introduced by a trailing '{'.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004954 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004955 if (nesting_state.previous_stack_top and
4956 not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
4957 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
4958 # Not at toplevel, not within a class, and not within a namespace
4959 return
4960
avakulenko@google.com59146752014-08-11 20:20:55 +00004961 # Avoid initializer lists. We only need to scan back from the
4962 # current line for something that starts with ':'.
4963 #
4964 # We don't need to check the current line, since the '&' would
4965 # appear inside the second set of parentheses on the current line as
4966 # opposed to the first set.
4967 if linenum > 0:
4968 for i in xrange(linenum - 1, max(0, linenum - 10), -1):
4969 previous_line = clean_lines.elided[i]
4970 if not Search(r'[),]\s*$', previous_line):
4971 break
4972 if Match(r'^\s*:\s+\S', previous_line):
4973 return
4974
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004975 # Avoid preprocessors
4976 if Search(r'\\\s*$', line):
4977 return
4978
4979 # Avoid constructor initializer lists
4980 if IsInitializerList(clean_lines, linenum):
4981 return
4982
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004983 # We allow non-const references in a few standard places, like functions
4984 # called "swap()" or iostream operators like "<<" or ">>". Do not check
4985 # those function parameters.
4986 #
4987 # We also accept & in static_assert, which looks like a function but
4988 # it's actually a declaration expression.
4989 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
4990 r'operator\s*[<>][<>]|'
4991 r'static_assert|COMPILE_ASSERT'
4992 r')\s*\(')
4993 if Search(whitelisted_functions, line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004994 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004995 elif not Search(r'\S+\([^)]*$', line):
4996 # Don't see a whitelisted function on this line. Actually we
4997 # didn't see any function name on this line, so this is likely a
4998 # multi-line parameter list. Try a bit harder to catch this case.
4999 for i in xrange(2):
5000 if (linenum > i and
5001 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005002 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005003
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005004 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
5005 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005006 if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
5007 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005008 error(filename, linenum, 'runtime/references', 2,
5009 'Is this a non-const reference? '
5010 'If so, make const or use a pointer: ' +
5011 ReplaceAll(' *<', '<', parameter))
5012
5013
5014def CheckCasts(filename, clean_lines, linenum, error):
5015 """Various cast related checks.
5016
5017 Args:
5018 filename: The name of the current file.
5019 clean_lines: A CleansedLines instance containing the file.
5020 linenum: The number of the line to check.
5021 error: The function to call with any errors found.
5022 """
5023 line = clean_lines.elided[linenum]
5024
5025 # Check to see if they're using an conversion function cast.
5026 # I just try to capture the most common basic types, though there are more.
5027 # Parameterless conversion functions, such as bool(), are allowed as they are
5028 # probably a member operator declaration or default constructor.
5029 match = Search(
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005030 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005031 r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
5032 r'(\([^)].*)', line)
5033 expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
5034 if match and not expecting_function:
5035 matched_type = match.group(2)
5036
5037 # matched_new_or_template is used to silence two false positives:
5038 # - New operators
5039 # - Template arguments with function types
5040 #
5041 # For template arguments, we match on types immediately following
5042 # an opening bracket without any spaces. This is a fast way to
5043 # silence the common case where the function type is the first
5044 # template argument. False negative with less-than comparison is
5045 # avoided because those operators are usually followed by a space.
5046 #
5047 # function<double(double)> // bracket + no space = false positive
5048 # value < double(42) // bracket + space = true positive
5049 matched_new_or_template = match.group(1)
5050
avakulenko@google.com59146752014-08-11 20:20:55 +00005051 # Avoid arrays by looking for brackets that come after the closing
5052 # parenthesis.
5053 if Match(r'\([^()]+\)\s*\[', match.group(3)):
5054 return
5055
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005056 # Other things to ignore:
5057 # - Function pointers
5058 # - Casts to pointer types
5059 # - Placement new
5060 # - Alias declarations
5061 matched_funcptr = match.group(3)
5062 if (matched_new_or_template is None and
5063 not (matched_funcptr and
5064 (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5065 matched_funcptr) or
5066 matched_funcptr.startswith('(*)'))) and
5067 not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
5068 not Search(r'new\(\S+\)\s*' + matched_type, line)):
5069 error(filename, linenum, 'readability/casting', 4,
5070 'Using deprecated casting style. '
5071 'Use static_cast<%s>(...) instead' %
5072 matched_type)
5073
5074 if not expecting_function:
avakulenko@google.com59146752014-08-11 20:20:55 +00005075 CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005076 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5077
5078 # This doesn't catch all cases. Consider (const char * const)"hello".
5079 #
5080 # (char *) "foo" should always be a const_cast (reinterpret_cast won't
5081 # compile).
avakulenko@google.com59146752014-08-11 20:20:55 +00005082 if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
5083 r'\((char\s?\*+\s?)\)\s*"', error):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005084 pass
5085 else:
5086 # Check pointer casts for other than string constants
avakulenko@google.com59146752014-08-11 20:20:55 +00005087 CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
5088 r'\((\w+\s?\*+\s?)\)', error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005089
5090 # In addition, we look for people taking the address of a cast. This
5091 # is dangerous -- casts can assign to temporaries, so the pointer doesn't
5092 # point where you think.
avakulenko@google.com59146752014-08-11 20:20:55 +00005093 #
5094 # Some non-identifier character is required before the '&' for the
5095 # expression to be recognized as a cast. These are casts:
5096 # expression = &static_cast<int*>(temporary());
5097 # function(&(int*)(temporary()));
5098 #
5099 # This is not a cast:
5100 # reference_type&(int* function_param);
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005101 match = Search(
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005102 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
avakulenko@google.com59146752014-08-11 20:20:55 +00005103 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005104 if match:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005105 # Try a better error message when the & is bound to something
5106 # dereferenced by the casted pointer, as opposed to the casted
5107 # pointer itself.
5108 parenthesis_error = False
5109 match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5110 if match:
5111 _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
5112 if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
5113 _, y2, x2 = CloseExpression(clean_lines, y1, x1)
5114 if x2 >= 0:
5115 extended_line = clean_lines.elided[y2][x2:]
5116 if y2 < clean_lines.NumLines() - 1:
5117 extended_line += clean_lines.elided[y2 + 1]
5118 if Match(r'\s*(?:->|\[)', extended_line):
5119 parenthesis_error = True
5120
5121 if parenthesis_error:
5122 error(filename, linenum, 'readability/casting', 4,
5123 ('Are you taking an address of something dereferenced '
5124 'from a cast? Wrapping the dereferenced expression in '
5125 'parentheses will make the binding more obvious'))
5126 else:
5127 error(filename, linenum, 'runtime/casting', 4,
5128 ('Are you taking an address of a cast? '
5129 'This is dangerous: could be a temp var. '
5130 'Take the address before doing the cast, rather than after'))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005131
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005132
avakulenko@google.com59146752014-08-11 20:20:55 +00005133def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005134 """Checks for a C-style cast by looking for the pattern.
5135
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005136 Args:
5137 filename: The name of the current file.
avakulenko@google.com59146752014-08-11 20:20:55 +00005138 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005139 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005140 cast_type: The string for the C++ cast to recommend. This is either
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005141 reinterpret_cast, static_cast, or const_cast, depending.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005142 pattern: The regular expression used to find C-style casts.
5143 error: The function to call with any errors found.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005144
5145 Returns:
5146 True if an error was emitted.
5147 False otherwise.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005148 """
avakulenko@google.com59146752014-08-11 20:20:55 +00005149 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005150 match = Search(pattern, line)
5151 if not match:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005152 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005153
avakulenko@google.com59146752014-08-11 20:20:55 +00005154 # Exclude lines with keywords that tend to look like casts
5155 context = line[0:match.start(1) - 1]
5156 if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5157 return False
5158
5159 # Try expanding current context to see if we one level of
5160 # parentheses inside a macro.
5161 if linenum > 0:
5162 for i in xrange(linenum - 1, max(0, linenum - 5), -1):
5163 context = clean_lines.elided[i] + context
5164 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005165 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005166
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005167 # operator++(int) and operator--(int)
avakulenko@google.com59146752014-08-11 20:20:55 +00005168 if context.endswith(' operator++') or context.endswith(' operator--'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005169 return False
5170
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005171 # A single unnamed argument for a function tends to look like old style cast.
5172 # If we see those, don't issue warnings for deprecated casts.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005173 remainder = line[match.end(0):]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005174 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005175 remainder):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005176 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005177
5178 # At this point, all that should be left is actual casts.
5179 error(filename, linenum, 'readability/casting', 4,
5180 'Using C-style cast. Use %s<%s>(...) instead' %
5181 (cast_type, match.group(1)))
5182
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005183 return True
5184
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005185
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005186def ExpectingFunctionArgs(clean_lines, linenum):
5187 """Checks whether where function type arguments are expected.
5188
5189 Args:
5190 clean_lines: A CleansedLines instance containing the file.
5191 linenum: The number of the line to check.
5192
5193 Returns:
5194 True if the line at 'linenum' is inside something that expects arguments
5195 of function types.
5196 """
5197 line = clean_lines.elided[linenum]
5198 return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
5199 (linenum >= 2 and
5200 (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5201 clean_lines.elided[linenum - 1]) or
5202 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5203 clean_lines.elided[linenum - 2]) or
5204 Search(r'\bstd::m?function\s*\<\s*$',
5205 clean_lines.elided[linenum - 1]))))
5206
5207
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005208_HEADERS_CONTAINING_TEMPLATES = (
5209 ('<deque>', ('deque',)),
5210 ('<functional>', ('unary_function', 'binary_function',
5211 'plus', 'minus', 'multiplies', 'divides', 'modulus',
5212 'negate',
5213 'equal_to', 'not_equal_to', 'greater', 'less',
5214 'greater_equal', 'less_equal',
5215 'logical_and', 'logical_or', 'logical_not',
5216 'unary_negate', 'not1', 'binary_negate', 'not2',
5217 'bind1st', 'bind2nd',
5218 'pointer_to_unary_function',
5219 'pointer_to_binary_function',
5220 'ptr_fun',
5221 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
5222 'mem_fun_ref_t',
5223 'const_mem_fun_t', 'const_mem_fun1_t',
5224 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
5225 'mem_fun_ref',
5226 )),
5227 ('<limits>', ('numeric_limits',)),
5228 ('<list>', ('list',)),
5229 ('<map>', ('map', 'multimap',)),
lhchavez2d1b6da2016-07-13 10:40:01 -07005230 ('<memory>', ('allocator', 'make_shared', 'make_unique', 'shared_ptr',
5231 'unique_ptr', 'weak_ptr')),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005232 ('<queue>', ('queue', 'priority_queue',)),
5233 ('<set>', ('set', 'multiset',)),
5234 ('<stack>', ('stack',)),
5235 ('<string>', ('char_traits', 'basic_string',)),
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005236 ('<tuple>', ('tuple',)),
lhchavez2d1b6da2016-07-13 10:40:01 -07005237 ('<unordered_map>', ('unordered_map', 'unordered_multimap')),
5238 ('<unordered_set>', ('unordered_set', 'unordered_multiset')),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005239 ('<utility>', ('pair',)),
5240 ('<vector>', ('vector',)),
5241
5242 # gcc extensions.
5243 # Note: std::hash is their hash, ::hash is our hash
5244 ('<hash_map>', ('hash_map', 'hash_multimap',)),
5245 ('<hash_set>', ('hash_set', 'hash_multiset',)),
5246 ('<slist>', ('slist',)),
5247 )
5248
skym@chromium.org3990c412016-02-05 20:55:12 +00005249_HEADERS_MAYBE_TEMPLATES = (
5250 ('<algorithm>', ('copy', 'max', 'min', 'min_element', 'sort',
5251 'transform',
5252 )),
lhchavez2d1b6da2016-07-13 10:40:01 -07005253 ('<utility>', ('forward', 'make_pair', 'move', 'swap')),
skym@chromium.org3990c412016-02-05 20:55:12 +00005254 )
5255
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005256_RE_PATTERN_STRING = re.compile(r'\bstring\b')
5257
skym@chromium.org3990c412016-02-05 20:55:12 +00005258_re_pattern_headers_maybe_templates = []
5259for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
5260 for _template in _templates:
5261 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
5262 # type::max().
5263 _re_pattern_headers_maybe_templates.append(
5264 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
5265 _template,
5266 _header))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005267
skym@chromium.org3990c412016-02-05 20:55:12 +00005268# Other scripts may reach in and modify this pattern.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005269_re_pattern_templates = []
5270for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
5271 for _template in _templates:
5272 _re_pattern_templates.append(
5273 (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
5274 _template + '<>',
5275 _header))
5276
5277
erg@google.com6317a9c2009-06-25 00:28:19 +00005278def FilesBelongToSameModule(filename_cc, filename_h):
5279 """Check if these two filenames belong to the same module.
5280
5281 The concept of a 'module' here is a as follows:
5282 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
5283 same 'module' if they are in the same directory.
5284 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
5285 to belong to the same module here.
5286
5287 If the filename_cc contains a longer path than the filename_h, for example,
5288 '/absolute/path/to/base/sysinfo.cc', and this file would include
5289 'base/sysinfo.h', this function also produces the prefix needed to open the
5290 header. This is used by the caller of this function to more robustly open the
5291 header file. We don't have access to the real include paths in this context,
5292 so we need this guesswork here.
5293
5294 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
5295 according to this implementation. Because of this, this function gives
5296 some false positives. This should be sufficiently rare in practice.
5297
5298 Args:
5299 filename_cc: is the path for the .cc file
5300 filename_h: is the path for the header path
5301
5302 Returns:
5303 Tuple with a bool and a string:
5304 bool: True if filename_cc and filename_h belong to the same module.
5305 string: the additional prefix needed to open the header file.
5306 """
5307
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005308 fileinfo = FileInfo(filename_cc)
5309 if not fileinfo.IsSource():
erg@google.com6317a9c2009-06-25 00:28:19 +00005310 return (False, '')
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005311 filename_cc = filename_cc[:-len(fileinfo.Extension())]
5312 matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName())
5313 if matched_test_suffix:
5314 filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
erg@google.com6317a9c2009-06-25 00:28:19 +00005315 filename_cc = filename_cc.replace('/public/', '/')
5316 filename_cc = filename_cc.replace('/internal/', '/')
5317
5318 if not filename_h.endswith('.h'):
5319 return (False, '')
5320 filename_h = filename_h[:-len('.h')]
5321 if filename_h.endswith('-inl'):
5322 filename_h = filename_h[:-len('-inl')]
5323 filename_h = filename_h.replace('/public/', '/')
5324 filename_h = filename_h.replace('/internal/', '/')
5325
5326 files_belong_to_same_module = filename_cc.endswith(filename_h)
5327 common_path = ''
5328 if files_belong_to_same_module:
5329 common_path = filename_cc[:-len(filename_h)]
5330 return files_belong_to_same_module, common_path
5331
5332
avakulenko@google.com59146752014-08-11 20:20:55 +00005333def UpdateIncludeState(filename, include_dict, io=codecs):
5334 """Fill up the include_dict with new includes found from the file.
erg@google.com6317a9c2009-06-25 00:28:19 +00005335
5336 Args:
5337 filename: the name of the header to read.
avakulenko@google.com59146752014-08-11 20:20:55 +00005338 include_dict: a dictionary in which the headers are inserted.
erg@google.com6317a9c2009-06-25 00:28:19 +00005339 io: The io factory to use to read the file. Provided for testability.
5340
5341 Returns:
avakulenko@google.com59146752014-08-11 20:20:55 +00005342 True if a header was successfully added. False otherwise.
erg@google.com6317a9c2009-06-25 00:28:19 +00005343 """
5344 headerfile = None
5345 try:
5346 headerfile = io.open(filename, 'r', 'utf8', 'replace')
5347 except IOError:
5348 return False
5349 linenum = 0
5350 for line in headerfile:
5351 linenum += 1
5352 clean_line = CleanseComments(line)
5353 match = _RE_PATTERN_INCLUDE.search(clean_line)
5354 if match:
5355 include = match.group(2)
avakulenko@google.com59146752014-08-11 20:20:55 +00005356 include_dict.setdefault(include, linenum)
erg@google.com6317a9c2009-06-25 00:28:19 +00005357 return True
5358
5359
5360def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
5361 io=codecs):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005362 """Reports for missing stl includes.
5363
5364 This function will output warnings to make sure you are including the headers
5365 necessary for the stl containers and functions that you use. We only give one
5366 reason to include a header. For example, if you use both equal_to<> and
5367 less<> in a .h file, only one (the latter in the file) of these will be
5368 reported as a reason to include the <functional>.
5369
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005370 Args:
5371 filename: The name of the current file.
5372 clean_lines: A CleansedLines instance containing the file.
5373 include_state: An _IncludeState instance.
5374 error: The function to call with any errors found.
erg@google.com6317a9c2009-06-25 00:28:19 +00005375 io: The IO factory to use to read the header file. Provided for unittest
5376 injection.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005377 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005378 required = {} # A map of header name to linenumber and the template entity.
5379 # Example of required: { '<functional>': (1219, 'less<>') }
5380
5381 for linenum in xrange(clean_lines.NumLines()):
5382 line = clean_lines.elided[linenum]
5383 if not line or line[0] == '#':
5384 continue
5385
5386 # String is special -- it is a non-templatized type in STL.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005387 matched = _RE_PATTERN_STRING.search(line)
5388 if matched:
erg@google.com35589e62010-11-17 18:58:16 +00005389 # Don't warn about strings in non-STL namespaces:
5390 # (We check only the first match per line; good enough.)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005391 prefix = line[:matched.start()]
erg@google.com35589e62010-11-17 18:58:16 +00005392 if prefix.endswith('std::') or not prefix.endswith('::'):
5393 required['<string>'] = (linenum, 'string')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005394
skym@chromium.org3990c412016-02-05 20:55:12 +00005395 for pattern, template, header in _re_pattern_headers_maybe_templates:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005396 if pattern.search(line):
5397 required[header] = (linenum, template)
5398
5399 # The following function is just a speed up, no semantics are changed.
5400 if not '<' in line: # Reduces the cpu time usage by skipping lines.
5401 continue
5402
5403 for pattern, template, header in _re_pattern_templates:
lhchavez9b2173c2016-07-13 10:20:07 -07005404 matched = pattern.search(line)
5405 if matched:
5406 # Don't warn about IWYU in non-STL namespaces:
5407 # (We check only the first match per line; good enough.)
5408 prefix = line[:matched.start()]
5409 if prefix.endswith('std::') or not prefix.endswith('::'):
5410 required[header] = (linenum, template)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005411
erg@google.com6317a9c2009-06-25 00:28:19 +00005412 # The policy is that if you #include something in foo.h you don't need to
5413 # include it again in foo.cc. Here, we will look at possible includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00005414 # Let's flatten the include_state include_list and copy it into a dictionary.
5415 include_dict = dict([item for sublist in include_state.include_list
5416 for item in sublist])
erg@google.com6317a9c2009-06-25 00:28:19 +00005417
avakulenko@google.com59146752014-08-11 20:20:55 +00005418 # Did we find the header for this file (if any) and successfully load it?
erg@google.com6317a9c2009-06-25 00:28:19 +00005419 header_found = False
5420
5421 # Use the absolute path so that matching works properly.
erg@chromium.org8f927562012-01-30 19:51:28 +00005422 abs_filename = FileInfo(filename).FullName()
erg@google.com6317a9c2009-06-25 00:28:19 +00005423
5424 # For Emacs's flymake.
5425 # If cpplint is invoked from Emacs's flymake, a temporary file is generated
5426 # by flymake and that file name might end with '_flymake.cc'. In that case,
5427 # restore original file name here so that the corresponding header file can be
5428 # found.
5429 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
5430 # instead of 'foo_flymake.h'
erg@google.com35589e62010-11-17 18:58:16 +00005431 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00005432
avakulenko@google.com59146752014-08-11 20:20:55 +00005433 # include_dict is modified during iteration, so we iterate over a copy of
erg@google.com6317a9c2009-06-25 00:28:19 +00005434 # the keys.
avakulenko@google.com59146752014-08-11 20:20:55 +00005435 header_keys = include_dict.keys()
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005436 for header in header_keys:
erg@google.com6317a9c2009-06-25 00:28:19 +00005437 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
5438 fullpath = common_path + header
avakulenko@google.com59146752014-08-11 20:20:55 +00005439 if same_module and UpdateIncludeState(fullpath, include_dict, io):
erg@google.com6317a9c2009-06-25 00:28:19 +00005440 header_found = True
5441
5442 # If we can't find the header file for a .cc, assume it's because we don't
5443 # know where to look. In that case we'll give up as we're not sure they
5444 # didn't include it in the .h file.
5445 # TODO(unknown): Do a better job of finding .h files so we are confident that
5446 # not having the .h file means there isn't one.
5447 if filename.endswith('.cc') and not header_found:
5448 return
5449
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005450 # All the lines have been processed, report the errors found.
5451 for required_header_unstripped in required:
5452 template = required[required_header_unstripped][1]
avakulenko@google.com59146752014-08-11 20:20:55 +00005453 if required_header_unstripped.strip('<>"') not in include_dict:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005454 error(filename, required[required_header_unstripped][0],
5455 'build/include_what_you_use', 4,
5456 'Add #include ' + required_header_unstripped + ' for ' + template)
5457
5458
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005459_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
5460
5461
5462def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
5463 """Check that make_pair's template arguments are deduced.
5464
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005465 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005466 specified explicitly, and such use isn't intended in any case.
5467
5468 Args:
5469 filename: The name of the current file.
5470 clean_lines: A CleansedLines instance containing the file.
5471 linenum: The number of the line to check.
5472 error: The function to call with any errors found.
5473 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005474 line = clean_lines.elided[linenum]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005475 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5476 if match:
5477 error(filename, linenum, 'build/explicit_make_pair',
5478 4, # 4 = high confidence
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005479 'For C++11-compatibility, omit template arguments from make_pair'
5480 ' OR use pair directly OR if appropriate, construct a pair directly')
avakulenko@google.com59146752014-08-11 20:20:55 +00005481
5482
avakulenko@google.com59146752014-08-11 20:20:55 +00005483def CheckRedundantVirtual(filename, clean_lines, linenum, error):
5484 """Check if line contains a redundant "virtual" function-specifier.
5485
5486 Args:
5487 filename: The name of the current file.
5488 clean_lines: A CleansedLines instance containing the file.
5489 linenum: The number of the line to check.
5490 error: The function to call with any errors found.
5491 """
5492 # Look for "virtual" on current line.
5493 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005494 virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
avakulenko@google.com59146752014-08-11 20:20:55 +00005495 if not virtual: return
5496
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005497 # Ignore "virtual" keywords that are near access-specifiers. These
5498 # are only used in class base-specifier and do not apply to member
5499 # functions.
5500 if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
5501 Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
5502 return
5503
5504 # Ignore the "virtual" keyword from virtual base classes. Usually
5505 # there is a column on the same line in these cases (virtual base
5506 # classes are rare in google3 because multiple inheritance is rare).
5507 if Match(r'^.*[^:]:[^:].*$', line): return
5508
avakulenko@google.com59146752014-08-11 20:20:55 +00005509 # Look for the next opening parenthesis. This is the start of the
5510 # parameter list (possibly on the next line shortly after virtual).
5511 # TODO(unknown): doesn't work if there are virtual functions with
5512 # decltype() or other things that use parentheses, but csearch suggests
5513 # that this is rare.
5514 end_col = -1
5515 end_line = -1
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005516 start_col = len(virtual.group(2))
avakulenko@google.com59146752014-08-11 20:20:55 +00005517 for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
5518 line = clean_lines.elided[start_line][start_col:]
5519 parameter_list = Match(r'^([^(]*)\(', line)
5520 if parameter_list:
5521 # Match parentheses to find the end of the parameter list
5522 (_, end_line, end_col) = CloseExpression(
5523 clean_lines, start_line, start_col + len(parameter_list.group(1)))
5524 break
5525 start_col = 0
5526
5527 if end_col < 0:
5528 return # Couldn't find end of parameter list, give up
5529
5530 # Look for "override" or "final" after the parameter list
5531 # (possibly on the next few lines).
5532 for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
5533 line = clean_lines.elided[i][end_col:]
5534 match = Search(r'\b(override|final)\b', line)
5535 if match:
5536 error(filename, linenum, 'readability/inheritance', 4,
5537 ('"virtual" is redundant since function is '
5538 'already declared as "%s"' % match.group(1)))
5539
5540 # Set end_col to check whole lines after we are done with the
5541 # first line.
5542 end_col = 0
5543 if Search(r'[^\w]\s*$', line):
5544 break
5545
5546
5547def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
5548 """Check if line contains a redundant "override" or "final" virt-specifier.
5549
5550 Args:
5551 filename: The name of the current file.
5552 clean_lines: A CleansedLines instance containing the file.
5553 linenum: The number of the line to check.
5554 error: The function to call with any errors found.
5555 """
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005556 # Look for closing parenthesis nearby. We need one to confirm where
5557 # the declarator ends and where the virt-specifier starts to avoid
5558 # false positives.
avakulenko@google.com59146752014-08-11 20:20:55 +00005559 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005560 declarator_end = line.rfind(')')
5561 if declarator_end >= 0:
5562 fragment = line[declarator_end:]
5563 else:
5564 if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
5565 fragment = line
5566 else:
5567 return
5568
5569 # Check that at most one of "override" or "final" is present, not both
5570 if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
avakulenko@google.com59146752014-08-11 20:20:55 +00005571 error(filename, linenum, 'readability/inheritance', 4,
5572 ('"override" is redundant since function is '
5573 'already declared as "final"'))
5574
5575
5576
5577
5578# Returns true if we are at a new block, and it is directly
5579# inside of a namespace.
5580def IsBlockInNameSpace(nesting_state, is_forward_declaration):
5581 """Checks that the new block is directly in a namespace.
5582
5583 Args:
5584 nesting_state: The _NestingState object that contains info about our state.
5585 is_forward_declaration: If the class is a forward declared class.
5586 Returns:
5587 Whether or not the new block is directly in a namespace.
5588 """
5589 if is_forward_declaration:
5590 if len(nesting_state.stack) >= 1 and (
5591 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
5592 return True
5593 else:
5594 return False
5595
5596 return (len(nesting_state.stack) > 1 and
5597 nesting_state.stack[-1].check_namespace_indentation and
5598 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5599
5600
5601def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
5602 raw_lines_no_comments, linenum):
5603 """This method determines if we should apply our namespace indentation check.
5604
5605 Args:
5606 nesting_state: The current nesting state.
5607 is_namespace_indent_item: If we just put a new class on the stack, True.
5608 If the top of the stack is not a class, or we did not recently
5609 add the class, False.
5610 raw_lines_no_comments: The lines without the comments.
5611 linenum: The current line number we are processing.
5612
5613 Returns:
5614 True if we should apply our namespace indentation check. Currently, it
5615 only works for classes and namespaces inside of a namespace.
5616 """
5617
5618 is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
5619 linenum)
5620
5621 if not (is_namespace_indent_item or is_forward_declaration):
5622 return False
5623
5624 # If we are in a macro, we do not want to check the namespace indentation.
5625 if IsMacroDefinition(raw_lines_no_comments, linenum):
5626 return False
5627
5628 return IsBlockInNameSpace(nesting_state, is_forward_declaration)
5629
5630
5631# Call this method if the line is directly inside of a namespace.
5632# If the line above is blank (excluding comments) or the start of
5633# an inner namespace, it cannot be indented.
5634def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
5635 error):
5636 line = raw_lines_no_comments[linenum]
5637 if Match(r'^\s+', line):
5638 error(filename, linenum, 'runtime/indentation_namespace', 4,
5639 'Do not indent within a namespace')
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005640
5641
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005642def ProcessLine(filename, file_extension, clean_lines, line,
5643 include_state, function_state, nesting_state, error,
5644 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005645 """Processes a single line in the file.
5646
5647 Args:
5648 filename: Filename of the file that is being processed.
5649 file_extension: The extension (dot not included) of the file.
5650 clean_lines: An array of strings, each representing a line of the file,
5651 with comments stripped.
5652 line: Number of line being processed.
5653 include_state: An _IncludeState instance in which the headers are inserted.
5654 function_state: A _FunctionState instance which counts function lines, etc.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005655 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005656 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005657 error: A callable to which errors are reported, which takes 4 arguments:
5658 filename, line number, error level, and message
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005659 extra_check_functions: An array of additional check functions that will be
5660 run on each source line. Each function takes 4
5661 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005662 """
5663 raw_lines = clean_lines.raw_lines
erg@google.com35589e62010-11-17 18:58:16 +00005664 ParseNolintSuppressions(filename, raw_lines[line], line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005665 nesting_state.Update(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005666 CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
5667 error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005668 if nesting_state.InAsmBlock(): return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005669 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005670 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005671 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005672 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005673 nesting_state, error)
5674 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005675 CheckForNonStandardConstructs(filename, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005676 nesting_state, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005677 CheckVlogArguments(filename, clean_lines, line, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005678 CheckPosixThreading(filename, clean_lines, line, error)
erg@google.com6317a9c2009-06-25 00:28:19 +00005679 CheckInvalidIncrement(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005680 CheckMakePairUsesDeduction(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005681 CheckRedundantVirtual(filename, clean_lines, line, error)
5682 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005683 for check_fn in extra_check_functions:
5684 check_fn(filename, clean_lines, line, error)
avakulenko@google.com17449932014-07-28 22:13:33 +00005685
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005686def FlagCxx11Features(filename, clean_lines, linenum, error):
5687 """Flag those c++11 features that we only allow in certain places.
5688
5689 Args:
5690 filename: The name of the current file.
5691 clean_lines: A CleansedLines instance containing the file.
5692 linenum: The number of the line to check.
5693 error: The function to call with any errors found.
5694 """
5695 line = clean_lines.elided[linenum]
5696
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005697 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005698
5699 # Flag unapproved C++ TR1 headers.
5700 if include and include.group(1).startswith('tr1/'):
5701 error(filename, linenum, 'build/c++tr1', 5,
5702 ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
5703
5704 # Flag unapproved C++11 headers.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005705 if include and include.group(1) in ('cfenv',
5706 'condition_variable',
5707 'fenv.h',
5708 'future',
5709 'mutex',
5710 'thread',
5711 'chrono',
5712 'ratio',
5713 'regex',
5714 'system_error',
5715 ):
5716 error(filename, linenum, 'build/c++11', 5,
5717 ('<%s> is an unapproved C++11 header.') % include.group(1))
5718
5719 # The only place where we need to worry about C++11 keywords and library
5720 # features in preprocessor directives is in macro definitions.
5721 if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
5722
5723 # These are classes and free functions. The classes are always
5724 # mentioned as std::*, but we only catch the free functions if
5725 # they're not found by ADL. They're alphabetical by header.
5726 for top_name in (
5727 # type_traits
5728 'alignment_of',
5729 'aligned_union',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005730 ):
5731 if Search(r'\bstd::%s\b' % top_name, line):
5732 error(filename, linenum, 'build/c++11', 5,
5733 ('std::%s is an unapproved C++11 class or function. Send c-style '
5734 'an example of where it would make your code more readable, and '
5735 'they may let you use it.') % top_name)
5736
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005737
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005738def FlagCxx14Features(filename, clean_lines, linenum, error):
5739 """Flag those C++14 features that we restrict.
5740
5741 Args:
5742 filename: The name of the current file.
5743 clean_lines: A CleansedLines instance containing the file.
5744 linenum: The number of the line to check.
5745 error: The function to call with any errors found.
5746 """
5747 line = clean_lines.elided[linenum]
5748
5749 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5750
5751 # Flag unapproved C++14 headers.
5752 if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
5753 error(filename, linenum, 'build/c++14', 5,
5754 ('<%s> is an unapproved C++14 header.') % include.group(1))
5755
5756
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005757def ProcessFileData(filename, file_extension, lines, error,
5758 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005759 """Performs lint checks and reports any errors to the given error function.
5760
5761 Args:
5762 filename: Filename of the file that is being processed.
5763 file_extension: The extension (dot not included) of the file.
5764 lines: An array of strings, each representing a line of the file, with the
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005765 last element being empty if the file is terminated with a newline.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005766 error: A callable to which errors are reported, which takes 4 arguments:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005767 filename, line number, error level, and message
5768 extra_check_functions: An array of additional check functions that will be
5769 run on each source line. Each function takes 4
5770 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005771 """
5772 lines = (['// marker so line numbers and indices both start at 1'] + lines +
5773 ['// marker so line numbers end in a known way'])
5774
5775 include_state = _IncludeState()
5776 function_state = _FunctionState()
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005777 nesting_state = NestingState()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005778
erg@google.com35589e62010-11-17 18:58:16 +00005779 ResetNolintSuppressions()
5780
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005781 CheckForCopyright(filename, lines, error)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005782 ProcessGlobalSuppresions(lines)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005783 RemoveMultiLineComments(filename, lines, error)
5784 clean_lines = CleansedLines(lines)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005785
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00005786 if file_extension == 'h':
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005787 CheckForHeaderGuard(filename, clean_lines, error)
5788
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005789 for line in xrange(clean_lines.NumLines()):
5790 ProcessLine(filename, file_extension, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005791 include_state, function_state, nesting_state, error,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005792 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005793 FlagCxx11Features(filename, clean_lines, line, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005794 nesting_state.CheckCompletedBlocks(filename, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005795
5796 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
skym@chromium.org3990c412016-02-05 20:55:12 +00005797
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005798 # Check that the .cc file has included its header if it exists.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005799 if _IsSourceExtension(file_extension):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005800 CheckHeaderFileIncluded(filename, include_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005801
5802 # We check here rather than inside ProcessLine so that we see raw
5803 # lines rather than "cleaned" lines.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005804 CheckForBadCharacters(filename, lines, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005805
5806 CheckForNewlineAtEOF(filename, lines, error)
5807
avakulenko@google.com17449932014-07-28 22:13:33 +00005808def ProcessConfigOverrides(filename):
5809 """ Loads the configuration files and processes the config overrides.
5810
5811 Args:
5812 filename: The name of the file being processed by the linter.
5813
5814 Returns:
5815 False if the current |filename| should not be processed further.
5816 """
5817
5818 abs_filename = os.path.abspath(filename)
5819 cfg_filters = []
5820 keep_looking = True
5821 while keep_looking:
5822 abs_path, base_name = os.path.split(abs_filename)
5823 if not base_name:
5824 break # Reached the root directory.
5825
5826 cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
5827 abs_filename = abs_path
5828 if not os.path.isfile(cfg_file):
5829 continue
5830
5831 try:
5832 with open(cfg_file) as file_handle:
5833 for line in file_handle:
5834 line, _, _ = line.partition('#') # Remove comments.
5835 if not line.strip():
5836 continue
5837
5838 name, _, val = line.partition('=')
5839 name = name.strip()
5840 val = val.strip()
5841 if name == 'set noparent':
5842 keep_looking = False
5843 elif name == 'filter':
5844 cfg_filters.append(val)
5845 elif name == 'exclude_files':
5846 # When matching exclude_files pattern, use the base_name of
5847 # the current file name or the directory name we are processing.
5848 # For example, if we are checking for lint errors in /foo/bar/baz.cc
5849 # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
5850 # file's "exclude_files" filter is meant to be checked against "bar"
5851 # and not "baz" nor "bar/baz.cc".
5852 if base_name:
5853 pattern = re.compile(val)
5854 if pattern.match(base_name):
5855 sys.stderr.write('Ignoring "%s": file excluded by "%s". '
5856 'File path component "%s" matches '
5857 'pattern "%s"\n' %
5858 (filename, cfg_file, base_name, val))
5859 return False
avakulenko@google.com68a4fa62014-08-25 16:26:18 +00005860 elif name == 'linelength':
5861 global _line_length
5862 try:
5863 _line_length = int(val)
5864 except ValueError:
5865 sys.stderr.write('Line length must be numeric.')
avakulenko@google.com17449932014-07-28 22:13:33 +00005866 else:
5867 sys.stderr.write(
5868 'Invalid configuration option (%s) in file %s\n' %
5869 (name, cfg_file))
5870
5871 except IOError:
5872 sys.stderr.write(
5873 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
5874 keep_looking = False
5875
5876 # Apply all the accumulated filters in reverse order (top-level directory
5877 # config options having the least priority).
5878 for filter in reversed(cfg_filters):
5879 _AddFilters(filter)
5880
5881 return True
5882
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005883
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005884def ProcessFile(filename, vlevel, extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005885 """Does google-lint on a single file.
5886
5887 Args:
5888 filename: The name of the file to parse.
5889
5890 vlevel: The level of errors to report. Every error of confidence
5891 >= verbose_level will be reported. 0 is a good default.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005892
5893 extra_check_functions: An array of additional check functions that will be
5894 run on each source line. Each function takes 4
5895 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005896 """
5897
5898 _SetVerboseLevel(vlevel)
avakulenko@google.com17449932014-07-28 22:13:33 +00005899 _BackupFilters()
5900
5901 if not ProcessConfigOverrides(filename):
5902 _RestoreFilters()
5903 return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005904
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005905 lf_lines = []
5906 crlf_lines = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005907 try:
5908 # Support the UNIX convention of using "-" for stdin. Note that
5909 # we are not opening the file with universal newline support
5910 # (which codecs doesn't support anyway), so the resulting lines do
5911 # contain trailing '\r' characters if we are reading a file that
5912 # has CRLF endings.
5913 # If after the split a trailing '\r' is present, it is removed
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005914 # below.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005915 if filename == '-':
5916 lines = codecs.StreamReaderWriter(sys.stdin,
5917 codecs.getreader('utf8'),
5918 codecs.getwriter('utf8'),
5919 'replace').read().split('\n')
5920 else:
5921 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
5922
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005923 # Remove trailing '\r'.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005924 # The -1 accounts for the extra trailing blank line we get from split()
5925 for linenum in range(len(lines) - 1):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005926 if lines[linenum].endswith('\r'):
5927 lines[linenum] = lines[linenum].rstrip('\r')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005928 crlf_lines.append(linenum + 1)
5929 else:
5930 lf_lines.append(linenum + 1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005931
5932 except IOError:
5933 sys.stderr.write(
5934 "Skipping input '%s': Can't open for reading\n" % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00005935 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005936 return
5937
5938 # Note, if no dot is found, this will give the entire filename as the ext.
5939 file_extension = filename[filename.rfind('.') + 1:]
5940
5941 # When reading from stdin, the extension is unknown, so no cpplint tests
5942 # should rely on the extension.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005943 if filename != '-' and file_extension not in _valid_extensions:
5944 sys.stderr.write('Ignoring %s; not a valid file name '
5945 '(%s)\n' % (filename, ', '.join(_valid_extensions)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005946 else:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005947 ProcessFileData(filename, file_extension, lines, Error,
5948 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005949
5950 # If end-of-line sequences are a mix of LF and CR-LF, issue
5951 # warnings on the lines with CR.
5952 #
5953 # Don't issue any warnings if all lines are uniformly LF or CR-LF,
5954 # since critique can handle these just fine, and the style guide
5955 # doesn't dictate a particular end of line sequence.
5956 #
5957 # We can't depend on os.linesep to determine what the desired
5958 # end-of-line sequence should be, since that will return the
5959 # server-side end-of-line sequence.
5960 if lf_lines and crlf_lines:
5961 # Warn on every line with CR. An alternative approach might be to
5962 # check whether the file is mostly CRLF or just LF, and warn on the
5963 # minority, we bias toward LF here since most tools prefer LF.
5964 for linenum in crlf_lines:
5965 Error(filename, linenum, 'whitespace/newline', 1,
5966 'Unexpected \\r (^M) found; better to use only \\n')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005967
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00005968 sys.stderr.write('Done processing %s\n' % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00005969 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005970
5971
5972def PrintUsage(message):
5973 """Prints a brief usage string and exits, optionally with an error message.
5974
5975 Args:
5976 message: The optional error message.
5977 """
5978 sys.stderr.write(_USAGE)
5979 if message:
5980 sys.exit('\nFATAL ERROR: ' + message)
5981 else:
5982 sys.exit(1)
5983
5984
5985def PrintCategories():
5986 """Prints a list of all the error-categories used by error messages.
5987
5988 These are the categories used to filter messages via --filter.
5989 """
erg@google.com35589e62010-11-17 18:58:16 +00005990 sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005991 sys.exit(0)
5992
5993
5994def ParseArguments(args):
5995 """Parses the command line arguments.
5996
5997 This may set the output format and verbosity level as side-effects.
5998
5999 Args:
6000 args: The command line arguments:
6001
6002 Returns:
6003 The list of filenames to lint.
6004 """
6005 try:
6006 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
erg@google.com26970fa2009-11-17 18:07:32 +00006007 'counting=',
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006008 'filter=',
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006009 'root=',
6010 'linelength=',
sdefresne263e9282016-07-19 02:14:22 -07006011 'extensions=',
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00006012 'project_root='])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006013 except getopt.GetoptError:
6014 PrintUsage('Invalid arguments.')
6015
6016 verbosity = _VerboseLevel()
6017 output_format = _OutputFormat()
6018 filters = ''
erg@google.com26970fa2009-11-17 18:07:32 +00006019 counting_style = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006020
6021 for (opt, val) in opts:
6022 if opt == '--help':
6023 PrintUsage(None)
6024 elif opt == '--output':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006025 if val not in ('emacs', 'vs7', 'eclipse'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006026 PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006027 output_format = val
6028 elif opt == '--verbose':
6029 verbosity = int(val)
6030 elif opt == '--filter':
6031 filters = val
erg@google.com6317a9c2009-06-25 00:28:19 +00006032 if not filters:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006033 PrintCategories()
erg@google.com26970fa2009-11-17 18:07:32 +00006034 elif opt == '--counting':
6035 if val not in ('total', 'toplevel', 'detailed'):
6036 PrintUsage('Valid counting options are total, toplevel, and detailed')
6037 counting_style = val
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006038 elif opt == '--root':
6039 global _root
6040 _root = val
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00006041 elif opt == '--project_root':
6042 global _project_root
6043 _project_root = val
6044 if not os.path.isabs(_project_root):
6045 PrintUsage('Project root must be an absolute path.')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006046 elif opt == '--linelength':
6047 global _line_length
6048 try:
6049 _line_length = int(val)
6050 except ValueError:
6051 PrintUsage('Line length must be digits.')
6052 elif opt == '--extensions':
6053 global _valid_extensions
6054 try:
6055 _valid_extensions = set(val.split(','))
6056 except ValueError:
qyearsley12fa6ff2016-08-24 09:18:40 -07006057 PrintUsage('Extensions must be comma separated list.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006058
6059 if not filenames:
6060 PrintUsage('No files were specified.')
6061
6062 _SetOutputFormat(output_format)
6063 _SetVerboseLevel(verbosity)
6064 _SetFilters(filters)
erg@google.com26970fa2009-11-17 18:07:32 +00006065 _SetCountingStyle(counting_style)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006066
6067 return filenames
6068
6069
6070def main():
6071 filenames = ParseArguments(sys.argv[1:])
6072
6073 # Change stderr to write with replacement characters so we don't die
6074 # if we try to print something containing non-ASCII characters.
6075 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
6076 codecs.getreader('utf8'),
6077 codecs.getwriter('utf8'),
6078 'replace')
6079
erg@google.com26970fa2009-11-17 18:07:32 +00006080 _cpplint_state.ResetErrorCounts()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006081 for filename in filenames:
6082 ProcessFile(filename, _cpplint_state.verbose_level)
Sergiy Byelozyorov7999d922018-06-22 09:25:54 +00006083 _cpplint_state.PrintErrorCounts()
erg@google.com26970fa2009-11-17 18:07:32 +00006084
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006085 sys.exit(_cpplint_state.error_count > 0)
6086
6087
6088if __name__ == '__main__':
6089 main()