blob: ac19165b357d187d392ad7fb59f3f014c7ba3535 [file] [log] [blame]
erg@chromium.orgd528f8b2012-05-11 17:31:08 +00001#!/usr/bin/env python
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002#
erg@google.com26970fa2009-11-17 18:07:32 +00003# Copyright (c) 2009 Google Inc. All rights reserved.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004#
erg@google.com26970fa2009-11-17 18:07:32 +00005# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00008#
erg@google.com26970fa2009-11-17 18:07:32 +00009# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000018#
erg@google.com26970fa2009-11-17 18:07:32 +000019# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000030
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000031"""Does google-lint on c++ files.
32
33The goal of this script is to identify places in the code that *may*
34be in non-compliance with google style. It does not attempt to fix
35up these problems -- the point is to educate. It does also not
36attempt to find all problems, or to ensure that everything it does
37find is legitimately a problem.
38
39In particular, we can get very confused by /* and // inside strings!
40We do a small hack, which is to ignore //'s with "'s after them on the
41same line, but it is far from perfect (in either direction).
42"""
43
44import codecs
mazda@chromium.org3fffcec2013-06-07 01:04:53 +000045import copy
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000046import getopt
47import math # for log
48import os
49import re
50import sre_compile
51import string
52import sys
53import unicodedata
54
55
56_USAGE = """
57Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +000058 [--counting=total|toplevel|detailed] [--root=subdir]
59 [--linelength=digits]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000060 <file> [file] ...
61
62 The style guidelines this tries to follow are those in
avakulenko@chromium.org764ce712016-05-06 23:03:41 +000063 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000064
65 Every problem is given a confidence score from 1-5, with 5 meaning we are
66 certain of the problem, and 1 meaning it could be a legitimate construct.
67 This will miss some errors, and is not a substitute for a code review.
68
erg@google.com35589e62010-11-17 18:58:16 +000069 To suppress false-positive errors of a certain category, add a
70 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*)
71 suppresses errors of all categories on that line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000072
73 The files passed in will be linted; at least one file must be provided.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +000074 Default linted extensions are .cc, .cpp, .cu, .cuh and .h. Change the
75 extensions with the --extensions flag.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +000076
77 Flags:
78
79 output=vs7
80 By default, the output is formatted to ease emacs parsing. Visual Studio
81 compatible output (vs7) may also be used. Other formats are unsupported.
82
83 verbose=#
84 Specify a number 0-5 to restrict errors to certain verbosity levels.
85
86 filter=-x,+y,...
87 Specify a comma-separated list of category-filters to apply: only
88 error messages whose category names pass the filters will be printed.
89 (Category names are printed with the message and look like
90 "[whitespace/indent]".) Filters are evaluated left to right.
91 "-FOO" and "FOO" means "do not print categories that start with FOO".
92 "+FOO" means "do print categories that start with FOO".
93
94 Examples: --filter=-whitespace,+whitespace/braces
95 --filter=whitespace,runtime/printf,+runtime/printf_format
96 --filter=-,+build/include_what_you_use
97
98 To see a list of all the categories used in cpplint, pass no arg:
99 --filter=
erg@google.com26970fa2009-11-17 18:07:32 +0000100
101 counting=total|toplevel|detailed
102 The total number of errors found is always printed. If
103 'toplevel' is provided, then the count of errors in each of
104 the top-level categories like 'build' and 'whitespace' will
105 also be printed. If 'detailed' is provided, then a count
106 is provided for each category like 'build/class'.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000107
108 root=subdir
109 The root directory used for deriving header guard CPP variable.
110 By default, the header guard CPP variable is calculated as the relative
111 path to the directory that contains .git, .hg, or .svn. When this flag
112 is specified, the relative path is calculated from the specified
113 directory. If the specified directory does not exist, this flag is
114 ignored.
115
116 Examples:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000117 Assuming that src/.git exists, the header guard CPP variables for
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000118 src/chrome/browser/ui/browser.h are:
119
120 No flag => CHROME_BROWSER_UI_BROWSER_H_
121 --root=chrome => BROWSER_UI_BROWSER_H_
122 --root=chrome/browser => UI_BROWSER_H_
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000123
124 linelength=digits
125 This is the allowed line length for the project. The default value is
126 80 characters.
127
128 Examples:
129 --linelength=120
130
131 extensions=extension,extension,...
132 The allowed file extensions that cpplint will check
133
134 Examples:
135 --extensions=hpp,cpp
avakulenko@google.com17449932014-07-28 22:13:33 +0000136
137 cpplint.py supports per-directory configurations specified in CPPLINT.cfg
138 files. CPPLINT.cfg file can contain a number of key=value pairs.
139 Currently the following options are supported:
140
141 set noparent
142 filter=+filter1,-filter2,...
143 exclude_files=regex
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000144 linelength=80
avakulenko@google.com17449932014-07-28 22:13:33 +0000145
146 "set noparent" option prevents cpplint from traversing directory tree
147 upwards looking for more .cfg files in parent directories. This option
148 is usually placed in the top-level project directory.
149
150 The "filter" option is similar in function to --filter flag. It specifies
151 message filters in addition to the |_DEFAULT_FILTERS| and those specified
152 through --filter command-line flag.
153
154 "exclude_files" allows to specify a regular expression to be matched against
155 a file name. If the expression matches, the file is skipped and not run
156 through liner.
157
avakulenko@google.com68a4fa62014-08-25 16:26:18 +0000158 "linelength" allows to specify the allowed line length for the project.
159
avakulenko@google.com17449932014-07-28 22:13:33 +0000160 CPPLINT.cfg has an effect on files in the same directory and all
161 sub-directories, unless overridden by a nested configuration file.
162
163 Example file:
164 filter=-build/include_order,+build/include_alpha
165 exclude_files=.*\.cc
166
167 The above example disables build/include_order warning and enables
168 build/include_alpha as well as excludes all .cc from being
169 processed by linter, in the current directory (where the .cfg
170 file is located) and all sub-directories.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000171"""
172
173# We categorize each error message we print. Here are the categories.
174# We want an explicit list so we can list them all in cpplint --filter=.
175# If you add a new error message with a new category, add it to the list
176# here! cpplint_unittest.py should tell you if you forget to do this.
erg@google.com35589e62010-11-17 18:58:16 +0000177_ERROR_CATEGORIES = [
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000178 'build/class',
179 'build/c++11',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000180 'build/c++14',
181 'build/c++tr1',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000182 'build/deprecated',
183 'build/endif_comment',
184 'build/explicit_make_pair',
185 'build/forward_decl',
186 'build/header_guard',
187 'build/include',
188 'build/include_alpha',
189 'build/include_order',
190 'build/include_what_you_use',
191 'build/namespaces',
192 'build/printf_format',
193 'build/storage_class',
194 'legal/copyright',
195 'readability/alt_tokens',
196 'readability/braces',
197 'readability/casting',
198 'readability/check',
199 'readability/constructors',
200 'readability/fn_size',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000201 'readability/inheritance',
202 'readability/multiline_comment',
203 'readability/multiline_string',
204 'readability/namespace',
205 'readability/nolint',
206 'readability/nul',
207 'readability/strings',
208 'readability/todo',
209 'readability/utf8',
210 'runtime/arrays',
211 'runtime/casting',
212 'runtime/explicit',
213 'runtime/int',
214 'runtime/init',
215 'runtime/invalid_increment',
216 'runtime/member_string_references',
217 'runtime/memset',
218 'runtime/indentation_namespace',
219 'runtime/operator',
220 'runtime/printf',
221 'runtime/printf_format',
222 'runtime/references',
223 'runtime/string',
224 'runtime/threadsafe_fn',
225 'runtime/vlog',
226 'whitespace/blank_line',
227 'whitespace/braces',
228 'whitespace/comma',
229 'whitespace/comments',
230 'whitespace/empty_conditional_body',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000231 'whitespace/empty_if_body',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000232 'whitespace/empty_loop_body',
233 'whitespace/end_of_line',
234 'whitespace/ending_newline',
235 'whitespace/forcolon',
236 'whitespace/indent',
237 'whitespace/line_length',
238 'whitespace/newline',
239 'whitespace/operators',
240 'whitespace/parens',
241 'whitespace/semicolon',
242 'whitespace/tab',
243 'whitespace/todo',
244 ]
245
246# These error categories are no longer enforced by cpplint, but for backwards-
247# compatibility they may still appear in NOLINT comments.
248_LEGACY_ERROR_CATEGORIES = [
249 'readability/streams',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000250 'readability/function',
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000251 ]
erg@google.com6317a9c2009-06-25 00:28:19 +0000252
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000253# The default state of the category filter. This is overridden by the --filter=
erg@google.com6317a9c2009-06-25 00:28:19 +0000254# flag. By default all errors are on, so only add here categories that should be
255# off by default (i.e., categories that must be enabled by the --filter= flags).
256# All entries here should start with a '-' or '+', as in the --filter= flag.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000257_DEFAULT_FILTERS = ['-build/include_alpha']
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000258
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000259# The default list of categories suppressed for C (not C++) files.
260_DEFAULT_C_SUPPRESSED_CATEGORIES = [
261 'readability/casting',
262 ]
263
264# The default list of categories suppressed for Linux Kernel files.
265_DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
266 'whitespace/tab',
267 ]
268
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000269# We used to check for high-bit characters, but after much discussion we
270# decided those were OK, as long as they were in UTF-8 and didn't represent
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000271# hard-coded international strings, which belong in a separate i18n file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000272
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000273# C++ headers
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000274_CPP_HEADERS = frozenset([
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000275 # Legacy
276 'algobase.h',
277 'algo.h',
278 'alloc.h',
279 'builtinbuf.h',
280 'bvector.h',
281 'complex.h',
282 'defalloc.h',
283 'deque.h',
284 'editbuf.h',
285 'fstream.h',
286 'function.h',
287 'hash_map',
288 'hash_map.h',
289 'hash_set',
290 'hash_set.h',
291 'hashtable.h',
292 'heap.h',
293 'indstream.h',
294 'iomanip.h',
295 'iostream.h',
296 'istream.h',
297 'iterator.h',
298 'list.h',
299 'map.h',
300 'multimap.h',
301 'multiset.h',
302 'ostream.h',
303 'pair.h',
304 'parsestream.h',
305 'pfstream.h',
306 'procbuf.h',
307 'pthread_alloc',
308 'pthread_alloc.h',
309 'rope',
310 'rope.h',
311 'ropeimpl.h',
312 'set.h',
313 'slist',
314 'slist.h',
315 'stack.h',
316 'stdiostream.h',
317 'stl_alloc.h',
318 'stl_relops.h',
319 'streambuf.h',
320 'stream.h',
321 'strfile.h',
322 'strstream.h',
323 'tempbuf.h',
324 'tree.h',
325 'type_traits.h',
326 'vector.h',
327 # 17.6.1.2 C++ library headers
328 'algorithm',
329 'array',
330 'atomic',
331 'bitset',
332 'chrono',
333 'codecvt',
334 'complex',
335 'condition_variable',
336 'deque',
337 'exception',
338 'forward_list',
339 'fstream',
340 'functional',
341 'future',
342 'initializer_list',
343 'iomanip',
344 'ios',
345 'iosfwd',
346 'iostream',
347 'istream',
348 'iterator',
349 'limits',
350 'list',
351 'locale',
352 'map',
353 'memory',
354 'mutex',
355 'new',
356 'numeric',
357 'ostream',
358 'queue',
359 'random',
360 'ratio',
361 'regex',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000362 'scoped_allocator',
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000363 'set',
364 'sstream',
365 'stack',
366 'stdexcept',
367 'streambuf',
368 'string',
369 'strstream',
370 'system_error',
371 'thread',
372 'tuple',
373 'typeindex',
374 'typeinfo',
375 'type_traits',
376 'unordered_map',
377 'unordered_set',
378 'utility',
379 'valarray',
380 'vector',
381 # 17.6.1.2 C++ headers for C library facilities
382 'cassert',
383 'ccomplex',
384 'cctype',
385 'cerrno',
386 'cfenv',
387 'cfloat',
388 'cinttypes',
389 'ciso646',
390 'climits',
391 'clocale',
392 'cmath',
393 'csetjmp',
394 'csignal',
395 'cstdalign',
396 'cstdarg',
397 'cstdbool',
398 'cstddef',
399 'cstdint',
400 'cstdio',
401 'cstdlib',
402 'cstring',
403 'ctgmath',
404 'ctime',
405 'cuchar',
406 'cwchar',
407 'cwctype',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000408 ])
409
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000410# Type names
411_TYPES = re.compile(
412 r'^(?:'
413 # [dcl.type.simple]
414 r'(char(16_t|32_t)?)|wchar_t|'
415 r'bool|short|int|long|signed|unsigned|float|double|'
416 # [support.types]
417 r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
418 # [cstdint.syn]
419 r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
420 r'(u?int(max|ptr)_t)|'
421 r')$')
422
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000423
avakulenko@google.com59146752014-08-11 20:20:55 +0000424# These headers are excluded from [build/include] and [build/include_order]
425# checks:
426# - Anything not following google file name conventions (containing an
427# uppercase character, such as Python.h or nsStringAPI.h, for example).
428# - Lua headers.
429_THIRD_PARTY_HEADERS_PATTERN = re.compile(
430 r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
431
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000432# Pattern for matching FileInfo.BaseName() against test file name
433_TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$'
434
435# Pattern that matches only complete whitespace, possibly across multiple lines.
436_EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL)
avakulenko@google.com59146752014-08-11 20:20:55 +0000437
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000438# Assertion macros. These are defined in base/logging.h and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000439# testing/base/public/gunit.h.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000440_CHECK_MACROS = [
erg@google.com6317a9c2009-06-25 00:28:19 +0000441 'DCHECK', 'CHECK',
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000442 'EXPECT_TRUE', 'ASSERT_TRUE',
443 'EXPECT_FALSE', 'ASSERT_FALSE',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000444 ]
445
erg@google.com6317a9c2009-06-25 00:28:19 +0000446# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000447_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
448
449for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
450 ('>=', 'GE'), ('>', 'GT'),
451 ('<=', 'LE'), ('<', 'LT')]:
erg@google.com6317a9c2009-06-25 00:28:19 +0000452 _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000453 _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
454 _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
455 _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000456
457for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
458 ('>=', 'LT'), ('>', 'LE'),
459 ('<=', 'GT'), ('<', 'GE')]:
460 _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
461 _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000462
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000463# Alternative tokens and their replacements. For full list, see section 2.5
464# Alternative tokens [lex.digraph] in the C++ standard.
465#
466# Digraphs (such as '%:') are not included here since it's a mess to
467# match those on a word boundary.
468_ALT_TOKEN_REPLACEMENT = {
469 'and': '&&',
470 'bitor': '|',
471 'or': '||',
472 'xor': '^',
473 'compl': '~',
474 'bitand': '&',
475 'and_eq': '&=',
476 'or_eq': '|=',
477 'xor_eq': '^=',
478 'not': '!',
479 'not_eq': '!='
480 }
481
482# Compile regular expression that matches all the above keywords. The "[ =()]"
483# bit is meant to avoid matching these keywords outside of boolean expressions.
484#
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000485# False positives include C-style multi-line comments and multi-line strings
486# but those have always been troublesome for cpplint.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000487_ALT_TOKEN_REPLACEMENT_PATTERN = re.compile(
488 r'[ =()](' + ('|'.join(_ALT_TOKEN_REPLACEMENT.keys())) + r')(?=[ (]|$)')
489
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000490
491# These constants define types of headers for use with
492# _IncludeState.CheckNextIncludeOrder().
493_C_SYS_HEADER = 1
494_CPP_SYS_HEADER = 2
495_LIKELY_MY_HEADER = 3
496_POSSIBLE_MY_HEADER = 4
497_OTHER_HEADER = 5
498
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000499# These constants define the current inline assembly state
500_NO_ASM = 0 # Outside of inline assembly block
501_INSIDE_ASM = 1 # Inside inline assembly block
502_END_ASM = 2 # Last line of inline assembly block
503_BLOCK_ASM = 3 # The whole block is an inline assembly block
504
505# Match start of assembly blocks
506_MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
507 r'(?:\s+(volatile|__volatile__))?'
508 r'\s*[{(]')
509
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000510# Match strings that indicate we're working on a C (not C++) file.
511_SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
512 r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
513
514# Match string that indicates we're working on a Linux Kernel file.
515_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000516
517_regexp_compile_cache = {}
518
erg@google.com35589e62010-11-17 18:58:16 +0000519# {str, set(int)}: a map from error categories to sets of linenumbers
520# on which those errors are expected and should be suppressed.
521_error_suppressions = {}
522
mazda@chromium.org3fffcec2013-06-07 01:04:53 +0000523# The root directory used for deriving header guard CPP variable.
524# This is set by --root flag.
525_root = None
526
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000527# The allowed line length of files.
528# This is set by --linelength flag.
529_line_length = 80
530
531# The allowed extensions for file names
532# This is set by --extensions flag.
533_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
534
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000535# {str, bool}: a map from error categories to booleans which indicate if the
536# category should be suppressed for every line.
537_global_error_suppressions = {}
538
539
erg@google.com35589e62010-11-17 18:58:16 +0000540def ParseNolintSuppressions(filename, raw_line, linenum, error):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000541 """Updates the global list of line error-suppressions.
erg@google.com35589e62010-11-17 18:58:16 +0000542
543 Parses any NOLINT comments on the current line, updating the global
544 error_suppressions store. Reports an error if the NOLINT comment
545 was malformed.
546
547 Args:
548 filename: str, the name of the input file.
549 raw_line: str, the line of input text, with comments.
550 linenum: int, the number of the current line.
551 error: function, an error handler.
552 """
avakulenko@google.com59146752014-08-11 20:20:55 +0000553 matched = Search(r'\bNOLINT(NEXTLINE)?\b(\([^)]+\))?', raw_line)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000554 if matched:
avakulenko@google.com59146752014-08-11 20:20:55 +0000555 if matched.group(1):
556 suppressed_line = linenum + 1
557 else:
558 suppressed_line = linenum
559 category = matched.group(2)
erg@google.com35589e62010-11-17 18:58:16 +0000560 if category in (None, '(*)'): # => "suppress all"
avakulenko@google.com59146752014-08-11 20:20:55 +0000561 _error_suppressions.setdefault(None, set()).add(suppressed_line)
erg@google.com35589e62010-11-17 18:58:16 +0000562 else:
563 if category.startswith('(') and category.endswith(')'):
564 category = category[1:-1]
565 if category in _ERROR_CATEGORIES:
avakulenko@google.com59146752014-08-11 20:20:55 +0000566 _error_suppressions.setdefault(category, set()).add(suppressed_line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000567 elif category not in _LEGACY_ERROR_CATEGORIES:
erg@google.com35589e62010-11-17 18:58:16 +0000568 error(filename, linenum, 'readability/nolint', 5,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000569 'Unknown NOLINT error category: %s' % category)
erg@google.com35589e62010-11-17 18:58:16 +0000570
571
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000572def ProcessGlobalSuppresions(lines):
573 """Updates the list of global error suppressions.
574
575 Parses any lint directives in the file that have global effect.
576
577 Args:
578 lines: An array of strings, each representing a line of the file, with the
579 last element being empty if the file is terminated with a newline.
580 """
581 for line in lines:
582 if _SEARCH_C_FILE.search(line):
583 for category in _DEFAULT_C_SUPPRESSED_CATEGORIES:
584 _global_error_suppressions[category] = True
585 if _SEARCH_KERNEL_FILE.search(line):
586 for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
587 _global_error_suppressions[category] = True
588
589
erg@google.com35589e62010-11-17 18:58:16 +0000590def ResetNolintSuppressions():
avakulenko@google.com59146752014-08-11 20:20:55 +0000591 """Resets the set of NOLINT suppressions to empty."""
erg@google.com35589e62010-11-17 18:58:16 +0000592 _error_suppressions.clear()
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000593 _global_error_suppressions.clear()
erg@google.com35589e62010-11-17 18:58:16 +0000594
595
596def IsErrorSuppressedByNolint(category, linenum):
597 """Returns true if the specified error category is suppressed on this line.
598
599 Consults the global error_suppressions map populated by
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000600 ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
erg@google.com35589e62010-11-17 18:58:16 +0000601
602 Args:
603 category: str, the category of the error.
604 linenum: int, the current line number.
605 Returns:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000606 bool, True iff the error should be suppressed due to a NOLINT comment or
607 global suppression.
erg@google.com35589e62010-11-17 18:58:16 +0000608 """
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000609 return (_global_error_suppressions.get(category, False) or
610 linenum in _error_suppressions.get(category, set()) or
erg@google.com35589e62010-11-17 18:58:16 +0000611 linenum in _error_suppressions.get(None, set()))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000612
avakulenko@google.comd39bbb52014-06-04 22:55:20 +0000613
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000614def Match(pattern, s):
615 """Matches the string with the pattern, caching the compiled regexp."""
616 # The regexp compilation caching is inlined in both Match and Search for
617 # performance reasons; factoring it out into a separate function turns out
618 # to be noticeably expensive.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000619 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000620 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
621 return _regexp_compile_cache[pattern].match(s)
622
623
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000624def ReplaceAll(pattern, rep, s):
625 """Replaces instances of pattern in a string with a replacement.
626
627 The compiled regex is kept in a cache shared by Match and Search.
628
629 Args:
630 pattern: regex pattern
631 rep: replacement text
632 s: search string
633
634 Returns:
635 string with replacements made (or original string if no replacements)
636 """
637 if pattern not in _regexp_compile_cache:
638 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
639 return _regexp_compile_cache[pattern].sub(rep, s)
640
641
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000642def Search(pattern, s):
643 """Searches the string for the pattern, caching the compiled regexp."""
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000644 if pattern not in _regexp_compile_cache:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000645 _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
646 return _regexp_compile_cache[pattern].search(s)
647
648
avakulenko@chromium.org764ce712016-05-06 23:03:41 +0000649def _IsSourceExtension(s):
650 """File extension (excluding dot) matches a source file extension."""
651 return s in ('c', 'cc', 'cpp', 'cxx')
652
653
avakulenko@google.com59146752014-08-11 20:20:55 +0000654class _IncludeState(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000655 """Tracks line numbers for includes, and the order in which includes appear.
656
avakulenko@google.com59146752014-08-11 20:20:55 +0000657 include_list contains list of lists of (header, line number) pairs.
658 It's a lists of lists rather than just one flat list to make it
659 easier to update across preprocessor boundaries.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000660
661 Call CheckNextIncludeOrder() once for each header in the file, passing
662 in the type constants defined above. Calls in an illegal order will
663 raise an _IncludeError with an appropriate error message.
664
665 """
666 # self._section will move monotonically through this set. If it ever
667 # needs to move backwards, CheckNextIncludeOrder will raise an error.
668 _INITIAL_SECTION = 0
669 _MY_H_SECTION = 1
670 _C_SECTION = 2
671 _CPP_SECTION = 3
672 _OTHER_H_SECTION = 4
673
674 _TYPE_NAMES = {
675 _C_SYS_HEADER: 'C system header',
676 _CPP_SYS_HEADER: 'C++ system header',
677 _LIKELY_MY_HEADER: 'header this file implements',
678 _POSSIBLE_MY_HEADER: 'header this file may implement',
679 _OTHER_HEADER: 'other header',
680 }
681 _SECTION_NAMES = {
682 _INITIAL_SECTION: "... nothing. (This can't be an error.)",
683 _MY_H_SECTION: 'a header this file implements',
684 _C_SECTION: 'C system header',
685 _CPP_SECTION: 'C++ system header',
686 _OTHER_H_SECTION: 'other header',
687 }
688
689 def __init__(self):
avakulenko@google.com59146752014-08-11 20:20:55 +0000690 self.include_list = [[]]
691 self.ResetSection('')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000692
avakulenko@google.com59146752014-08-11 20:20:55 +0000693 def FindHeader(self, header):
694 """Check if a header has already been included.
695
696 Args:
697 header: header to check.
698 Returns:
699 Line number of previous occurrence, or -1 if the header has not
700 been seen before.
701 """
702 for section_list in self.include_list:
703 for f in section_list:
704 if f[0] == header:
705 return f[1]
706 return -1
707
708 def ResetSection(self, directive):
709 """Reset section checking for preprocessor directive.
710
711 Args:
712 directive: preprocessor directive (e.g. "if", "else").
713 """
erg@google.com26970fa2009-11-17 18:07:32 +0000714 # The name of the current section.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000715 self._section = self._INITIAL_SECTION
erg@google.com26970fa2009-11-17 18:07:32 +0000716 # The path of last found header.
717 self._last_header = ''
718
avakulenko@google.com59146752014-08-11 20:20:55 +0000719 # Update list of includes. Note that we never pop from the
720 # include list.
721 if directive in ('if', 'ifdef', 'ifndef'):
722 self.include_list.append([])
723 elif directive in ('else', 'elif'):
724 self.include_list[-1] = []
725
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000726 def SetLastHeader(self, header_path):
727 self._last_header = header_path
728
erg@google.com26970fa2009-11-17 18:07:32 +0000729 def CanonicalizeAlphabeticalOrder(self, header_path):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +0000730 """Returns a path canonicalized for alphabetical comparison.
erg@google.com26970fa2009-11-17 18:07:32 +0000731
732 - replaces "-" with "_" so they both cmp the same.
733 - removes '-inl' since we don't require them to be after the main header.
734 - lowercase everything, just in case.
735
736 Args:
737 header_path: Path to be canonicalized.
738
739 Returns:
740 Canonicalized path.
741 """
742 return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
743
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000744 def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
erg@google.com26970fa2009-11-17 18:07:32 +0000745 """Check if a header is in alphabetical order with the previous header.
746
747 Args:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000748 clean_lines: A CleansedLines instance containing the file.
749 linenum: The number of the line to check.
750 header_path: Canonicalized header to be checked.
erg@google.com26970fa2009-11-17 18:07:32 +0000751
752 Returns:
753 Returns true if the header is in alphabetical order.
754 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +0000755 # If previous section is different from current section, _last_header will
756 # be reset to empty string, so it's always less than current header.
757 #
758 # If previous line was a blank line, assume that the headers are
759 # intentionally sorted the way they are.
760 if (self._last_header > header_path and
avakulenko@google.com255f2be2014-12-05 22:19:55 +0000761 Match(r'^\s*#\s*include\b', clean_lines.elided[linenum - 1])):
erg@google.com26970fa2009-11-17 18:07:32 +0000762 return False
erg@google.com26970fa2009-11-17 18:07:32 +0000763 return True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000764
765 def CheckNextIncludeOrder(self, header_type):
766 """Returns a non-empty error message if the next header is out of order.
767
768 This function also updates the internal state to be ready to check
769 the next include.
770
771 Args:
772 header_type: One of the _XXX_HEADER constants defined above.
773
774 Returns:
775 The empty string if the header is in the right order, or an
776 error message describing what's wrong.
777
778 """
779 error_message = ('Found %s after %s' %
780 (self._TYPE_NAMES[header_type],
781 self._SECTION_NAMES[self._section]))
782
erg@google.com26970fa2009-11-17 18:07:32 +0000783 last_section = self._section
784
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000785 if header_type == _C_SYS_HEADER:
786 if self._section <= self._C_SECTION:
787 self._section = self._C_SECTION
788 else:
erg@google.com26970fa2009-11-17 18:07:32 +0000789 self._last_header = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000790 return error_message
791 elif header_type == _CPP_SYS_HEADER:
792 if self._section <= self._CPP_SECTION:
793 self._section = self._CPP_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 == _LIKELY_MY_HEADER:
798 if self._section <= self._MY_H_SECTION:
799 self._section = self._MY_H_SECTION
800 else:
801 self._section = self._OTHER_H_SECTION
802 elif header_type == _POSSIBLE_MY_HEADER:
803 if self._section <= self._MY_H_SECTION:
804 self._section = self._MY_H_SECTION
805 else:
806 # This will always be the fallback because we're not sure
807 # enough that the header is associated with this file.
808 self._section = self._OTHER_H_SECTION
809 else:
810 assert header_type == _OTHER_HEADER
811 self._section = self._OTHER_H_SECTION
812
erg@google.com26970fa2009-11-17 18:07:32 +0000813 if last_section != self._section:
814 self._last_header = ''
815
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000816 return ''
817
818
819class _CppLintState(object):
820 """Maintains module-wide state.."""
821
822 def __init__(self):
823 self.verbose_level = 1 # global setting.
824 self.error_count = 0 # global count of reported errors
erg@google.com6317a9c2009-06-25 00:28:19 +0000825 # filters to apply when emitting error messages
826 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000827 # backup of filter list. Used to restore the state after each file.
828 self._filters_backup = self.filters[:]
erg@google.com26970fa2009-11-17 18:07:32 +0000829 self.counting = 'total' # In what way are we counting errors?
830 self.errors_by_category = {} # string to int dict storing error counts
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000831
832 # output format:
833 # "emacs" - format that emacs can parse (default)
834 # "vs7" - format that Microsoft Visual Studio 7 can parse
835 self.output_format = 'emacs'
836
837 def SetOutputFormat(self, output_format):
838 """Sets the output format for errors."""
839 self.output_format = output_format
840
841 def SetVerboseLevel(self, level):
842 """Sets the module's verbosity, and returns the previous setting."""
843 last_verbose_level = self.verbose_level
844 self.verbose_level = level
845 return last_verbose_level
846
erg@google.com26970fa2009-11-17 18:07:32 +0000847 def SetCountingStyle(self, counting_style):
848 """Sets the module's counting options."""
849 self.counting = counting_style
850
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000851 def SetFilters(self, filters):
852 """Sets the error-message filters.
853
854 These filters are applied when deciding whether to emit a given
855 error message.
856
857 Args:
858 filters: A string of comma-separated filters (eg "+whitespace/indent").
859 Each filter should start with + or -; else we die.
erg@google.com6317a9c2009-06-25 00:28:19 +0000860
861 Raises:
862 ValueError: The comma-separated filters did not all start with '+' or '-'.
863 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000864 """
erg@google.com6317a9c2009-06-25 00:28:19 +0000865 # Default filters always have less priority than the flag ones.
866 self.filters = _DEFAULT_FILTERS[:]
avakulenko@google.com17449932014-07-28 22:13:33 +0000867 self.AddFilters(filters)
868
869 def AddFilters(self, filters):
870 """ Adds more filters to the existing list of error-message filters. """
erg@google.com6317a9c2009-06-25 00:28:19 +0000871 for filt in filters.split(','):
872 clean_filt = filt.strip()
873 if clean_filt:
874 self.filters.append(clean_filt)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000875 for filt in self.filters:
876 if not (filt.startswith('+') or filt.startswith('-')):
877 raise ValueError('Every filter in --filters must start with + or -'
878 ' (%s does not)' % filt)
879
avakulenko@google.com17449932014-07-28 22:13:33 +0000880 def BackupFilters(self):
881 """ Saves the current filter list to backup storage."""
882 self._filters_backup = self.filters[:]
883
884 def RestoreFilters(self):
885 """ Restores filters previously backed up."""
886 self.filters = self._filters_backup[:]
887
erg@google.com26970fa2009-11-17 18:07:32 +0000888 def ResetErrorCounts(self):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000889 """Sets the module's error statistic back to zero."""
890 self.error_count = 0
erg@google.com26970fa2009-11-17 18:07:32 +0000891 self.errors_by_category = {}
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000892
erg@google.com26970fa2009-11-17 18:07:32 +0000893 def IncrementErrorCount(self, category):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000894 """Bumps the module's error statistic."""
895 self.error_count += 1
erg@google.com26970fa2009-11-17 18:07:32 +0000896 if self.counting in ('toplevel', 'detailed'):
897 if self.counting != 'detailed':
898 category = category.split('/')[0]
899 if category not in self.errors_by_category:
900 self.errors_by_category[category] = 0
901 self.errors_by_category[category] += 1
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000902
erg@google.com26970fa2009-11-17 18:07:32 +0000903 def PrintErrorCounts(self):
904 """Print a summary of errors by category, and the total."""
905 for category, count in self.errors_by_category.iteritems():
906 sys.stderr.write('Category \'%s\' errors found: %d\n' %
907 (category, count))
908 sys.stderr.write('Total errors found: %d\n' % self.error_count)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000909
910_cpplint_state = _CppLintState()
911
912
913def _OutputFormat():
914 """Gets the module's output format."""
915 return _cpplint_state.output_format
916
917
918def _SetOutputFormat(output_format):
919 """Sets the module's output format."""
920 _cpplint_state.SetOutputFormat(output_format)
921
922
923def _VerboseLevel():
924 """Returns the module's verbosity setting."""
925 return _cpplint_state.verbose_level
926
927
928def _SetVerboseLevel(level):
929 """Sets the module's verbosity, and returns the previous setting."""
930 return _cpplint_state.SetVerboseLevel(level)
931
932
erg@google.com26970fa2009-11-17 18:07:32 +0000933def _SetCountingStyle(level):
934 """Sets the module's counting options."""
935 _cpplint_state.SetCountingStyle(level)
936
937
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000938def _Filters():
939 """Returns the module's list of output filters, as a list."""
940 return _cpplint_state.filters
941
942
943def _SetFilters(filters):
944 """Sets the module's error-message filters.
945
946 These filters are applied when deciding whether to emit a given
947 error message.
948
949 Args:
950 filters: A string of comma-separated filters (eg "whitespace/indent").
951 Each filter should start with + or -; else we die.
952 """
953 _cpplint_state.SetFilters(filters)
954
avakulenko@google.com17449932014-07-28 22:13:33 +0000955def _AddFilters(filters):
956 """Adds more filter overrides.
avakulenko@google.com59146752014-08-11 20:20:55 +0000957
avakulenko@google.com17449932014-07-28 22:13:33 +0000958 Unlike _SetFilters, this function does not reset the current list of filters
959 available.
960
961 Args:
962 filters: A string of comma-separated filters (eg "whitespace/indent").
963 Each filter should start with + or -; else we die.
964 """
965 _cpplint_state.AddFilters(filters)
966
967def _BackupFilters():
968 """ Saves the current filter list to backup storage."""
969 _cpplint_state.BackupFilters()
970
971def _RestoreFilters():
972 """ Restores filters previously backed up."""
973 _cpplint_state.RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +0000974
975class _FunctionState(object):
976 """Tracks current function name and the number of lines in its body."""
977
978 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
979 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
980
981 def __init__(self):
982 self.in_a_function = False
983 self.lines_in_function = 0
984 self.current_function = ''
985
986 def Begin(self, function_name):
987 """Start analyzing function body.
988
989 Args:
990 function_name: The name of the function being tracked.
991 """
992 self.in_a_function = True
993 self.lines_in_function = 0
994 self.current_function = function_name
995
996 def Count(self):
997 """Count line in current function body."""
998 if self.in_a_function:
999 self.lines_in_function += 1
1000
1001 def Check(self, error, filename, linenum):
1002 """Report if too many lines in function body.
1003
1004 Args:
1005 error: The function to call with any errors found.
1006 filename: The name of the current file.
1007 linenum: The number of the line to check.
1008 """
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001009 if not self.in_a_function:
1010 return
1011
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001012 if Match(r'T(EST|est)', self.current_function):
1013 base_trigger = self._TEST_TRIGGER
1014 else:
1015 base_trigger = self._NORMAL_TRIGGER
1016 trigger = base_trigger * 2**_VerboseLevel()
1017
1018 if self.lines_in_function > trigger:
1019 error_level = int(math.log(self.lines_in_function / base_trigger, 2))
1020 # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
1021 if error_level > 5:
1022 error_level = 5
1023 error(filename, linenum, 'readability/fn_size', error_level,
1024 'Small and focused functions are preferred:'
1025 ' %s has %d non-comment lines'
1026 ' (error triggered by exceeding %d lines).' % (
1027 self.current_function, self.lines_in_function, trigger))
1028
1029 def End(self):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001030 """Stop analyzing function body."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001031 self.in_a_function = False
1032
1033
1034class _IncludeError(Exception):
1035 """Indicates a problem with the include order in a file."""
1036 pass
1037
1038
avakulenko@google.com59146752014-08-11 20:20:55 +00001039class FileInfo(object):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001040 """Provides utility functions for filenames.
1041
1042 FileInfo provides easy access to the components of a file's path
1043 relative to the project root.
1044 """
1045
1046 def __init__(self, filename):
1047 self._filename = filename
1048
1049 def FullName(self):
1050 """Make Windows paths like Unix."""
1051 return os.path.abspath(self._filename).replace('\\', '/')
1052
1053 def RepositoryName(self):
1054 """FullName after removing the local path to the repository.
1055
1056 If we have a real absolute path name here we can try to do something smart:
1057 detecting the root of the checkout and truncating /path/to/checkout from
1058 the name so that we get header guards that don't include things like
1059 "C:\Documents and Settings\..." or "/home/username/..." in them and thus
1060 people on different computers who have checked the source out to different
1061 locations won't see bogus errors.
1062 """
1063 fullname = self.FullName()
1064
1065 if os.path.exists(fullname):
1066 project_dir = os.path.dirname(fullname)
1067
1068 if os.path.exists(os.path.join(project_dir, ".svn")):
1069 # If there's a .svn file in the current directory, we recursively look
1070 # up the directory tree for the top of the SVN checkout
1071 root_dir = project_dir
1072 one_up_dir = os.path.dirname(root_dir)
1073 while os.path.exists(os.path.join(one_up_dir, ".svn")):
1074 root_dir = os.path.dirname(root_dir)
1075 one_up_dir = os.path.dirname(one_up_dir)
1076
1077 prefix = os.path.commonprefix([root_dir, project_dir])
1078 return fullname[len(prefix) + 1:]
1079
erg@chromium.org7956a872011-11-30 01:44:03 +00001080 # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
1081 # searching up from the current path.
kjellander@chromium.org95a5ad82016-04-22 19:29:18 +00001082 root_dir = os.path.dirname(fullname)
1083 while (root_dir != os.path.dirname(root_dir) and
1084 not os.path.exists(os.path.join(root_dir, ".git")) and
1085 not os.path.exists(os.path.join(root_dir, ".hg")) and
1086 not os.path.exists(os.path.join(root_dir, ".svn"))):
1087 root_dir = os.path.dirname(root_dir)
erg@google.com35589e62010-11-17 18:58:16 +00001088
1089 if (os.path.exists(os.path.join(root_dir, ".git")) or
erg@chromium.org7956a872011-11-30 01:44:03 +00001090 os.path.exists(os.path.join(root_dir, ".hg")) or
1091 os.path.exists(os.path.join(root_dir, ".svn"))):
erg@google.com35589e62010-11-17 18:58:16 +00001092 prefix = os.path.commonprefix([root_dir, project_dir])
1093 return fullname[len(prefix) + 1:]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001094
1095 # Don't know what to do; header guard warnings may be wrong...
1096 return fullname
1097
1098 def Split(self):
1099 """Splits the file into the directory, basename, and extension.
1100
1101 For 'chrome/browser/browser.cc', Split() would
1102 return ('chrome/browser', 'browser', '.cc')
1103
1104 Returns:
1105 A tuple of (directory, basename, extension).
1106 """
1107
1108 googlename = self.RepositoryName()
1109 project, rest = os.path.split(googlename)
1110 return (project,) + os.path.splitext(rest)
1111
1112 def BaseName(self):
1113 """File base name - text after the final slash, before the final period."""
1114 return self.Split()[1]
1115
1116 def Extension(self):
1117 """File extension - text following the final period."""
1118 return self.Split()[2]
1119
1120 def NoExtension(self):
1121 """File has no source file extension."""
1122 return '/'.join(self.Split()[0:2])
1123
1124 def IsSource(self):
1125 """File has a source file extension."""
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001126 return _IsSourceExtension(self.Extension()[1:])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001127
1128
erg@google.com35589e62010-11-17 18:58:16 +00001129def _ShouldPrintError(category, confidence, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001130 """If confidence >= verbose, category passes filter and is not suppressed."""
erg@google.com35589e62010-11-17 18:58:16 +00001131
1132 # There are three ways we might decide not to print an error message:
1133 # a "NOLINT(category)" comment appears in the source,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001134 # the verbosity level isn't high enough, or the filters filter it out.
erg@google.com35589e62010-11-17 18:58:16 +00001135 if IsErrorSuppressedByNolint(category, linenum):
1136 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001137
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001138 if confidence < _cpplint_state.verbose_level:
1139 return False
1140
1141 is_filtered = False
1142 for one_filter in _Filters():
1143 if one_filter.startswith('-'):
1144 if category.startswith(one_filter[1:]):
1145 is_filtered = True
1146 elif one_filter.startswith('+'):
1147 if category.startswith(one_filter[1:]):
1148 is_filtered = False
1149 else:
1150 assert False # should have been checked for in SetFilter.
1151 if is_filtered:
1152 return False
1153
1154 return True
1155
1156
1157def Error(filename, linenum, category, confidence, message):
1158 """Logs the fact we've found a lint error.
1159
1160 We log where the error was found, and also our confidence in the error,
1161 that is, how certain we are this is a legitimate style regression, and
1162 not a misidentification or a use that's sometimes justified.
1163
erg@google.com35589e62010-11-17 18:58:16 +00001164 False positives can be suppressed by the use of
1165 "cpplint(category)" comments on the offending line. These are
1166 parsed into _error_suppressions.
1167
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001168 Args:
1169 filename: The name of the file containing the error.
1170 linenum: The number of the line containing the error.
1171 category: A string used to describe the "category" this bug
1172 falls under: "whitespace", say, or "runtime". Categories
1173 may have a hierarchy separated by slashes: "whitespace/indent".
1174 confidence: A number from 1-5 representing a confidence score for
1175 the error, with 5 meaning that we are certain of the problem,
1176 and 1 meaning that it could be a legitimate construct.
1177 message: The error message.
1178 """
erg@google.com35589e62010-11-17 18:58:16 +00001179 if _ShouldPrintError(category, confidence, linenum):
erg@google.com26970fa2009-11-17 18:07:32 +00001180 _cpplint_state.IncrementErrorCount(category)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001181 if _cpplint_state.output_format == 'vs7':
1182 sys.stderr.write('%s(%s): %s [%s] [%d]\n' % (
1183 filename, linenum, message, category, confidence))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001184 elif _cpplint_state.output_format == 'eclipse':
1185 sys.stderr.write('%s:%s: warning: %s [%s] [%d]\n' % (
1186 filename, linenum, message, category, confidence))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001187 else:
1188 sys.stderr.write('%s:%s: %s [%s] [%d]\n' % (
1189 filename, linenum, message, category, confidence))
1190
1191
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001192# Matches standard C++ escape sequences per 2.13.2.3 of the C++ standard.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001193_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
1194 r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001195# Match a single C style comment on the same line.
1196_RE_PATTERN_C_COMMENTS = r'/\*(?:[^*]|\*(?!/))*\*/'
1197# Matches multi-line C style comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001198# This RE is a little bit more complicated than one might expect, because we
1199# have to take care of space removals tools so we can handle comments inside
1200# statements better.
1201# The current rule is: We only clear spaces from both sides when we're at the
1202# end of the line. Otherwise, we try to remove spaces from the right side,
1203# if this doesn't work we try on left side but only if there's a non-character
1204# on the right.
1205_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001206 r'(\s*' + _RE_PATTERN_C_COMMENTS + r'\s*$|' +
1207 _RE_PATTERN_C_COMMENTS + r'\s+|' +
1208 r'\s+' + _RE_PATTERN_C_COMMENTS + r'(?=\W)|' +
1209 _RE_PATTERN_C_COMMENTS + r')')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001210
1211
1212def IsCppString(line):
1213 """Does line terminate so, that the next symbol is in string constant.
1214
1215 This function does not consider single-line nor multi-line comments.
1216
1217 Args:
1218 line: is a partial line of code starting from the 0..n.
1219
1220 Returns:
1221 True, if next character appended to 'line' is inside a
1222 string constant.
1223 """
1224
1225 line = line.replace(r'\\', 'XX') # after this, \\" does not match to \"
1226 return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
1227
1228
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001229def CleanseRawStrings(raw_lines):
1230 """Removes C++11 raw strings from lines.
1231
1232 Before:
1233 static const char kData[] = R"(
1234 multi-line string
1235 )";
1236
1237 After:
1238 static const char kData[] = ""
1239 (replaced by blank line)
1240 "";
1241
1242 Args:
1243 raw_lines: list of raw lines.
1244
1245 Returns:
1246 list of lines with C++11 raw strings replaced by empty strings.
1247 """
1248
1249 delimiter = None
1250 lines_without_raw_strings = []
1251 for line in raw_lines:
1252 if delimiter:
1253 # Inside a raw string, look for the end
1254 end = line.find(delimiter)
1255 if end >= 0:
1256 # Found the end of the string, match leading space for this
1257 # line and resume copying the original lines, and also insert
1258 # a "" on the last line.
1259 leading_space = Match(r'^(\s*)\S', line)
1260 line = leading_space.group(1) + '""' + line[end + len(delimiter):]
1261 delimiter = None
1262 else:
1263 # Haven't found the end yet, append a blank line.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001264 line = '""'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001265
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001266 # Look for beginning of a raw string, and replace them with
1267 # empty strings. This is done in a loop to handle multiple raw
1268 # strings on the same line.
1269 while delimiter is None:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001270 # Look for beginning of a raw string.
1271 # See 2.14.15 [lex.string] for syntax.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001272 #
1273 # Once we have matched a raw string, we check the prefix of the
1274 # line to make sure that the line is not part of a single line
1275 # comment. It's done this way because we remove raw strings
1276 # before removing comments as opposed to removing comments
1277 # before removing raw strings. This is because there are some
1278 # cpplint checks that requires the comments to be preserved, but
1279 # we don't want to check comments that are inside raw strings.
1280 matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1281 if (matched and
1282 not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
1283 matched.group(1))):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001284 delimiter = ')' + matched.group(2) + '"'
1285
1286 end = matched.group(3).find(delimiter)
1287 if end >= 0:
1288 # Raw string ended on same line
1289 line = (matched.group(1) + '""' +
1290 matched.group(3)[end + len(delimiter):])
1291 delimiter = None
1292 else:
1293 # Start of a multi-line raw string
1294 line = matched.group(1) + '""'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001295 else:
1296 break
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001297
1298 lines_without_raw_strings.append(line)
1299
1300 # TODO(unknown): if delimiter is not None here, we might want to
1301 # emit a warning for unterminated string.
1302 return lines_without_raw_strings
1303
1304
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001305def FindNextMultiLineCommentStart(lines, lineix):
1306 """Find the beginning marker for a multiline comment."""
1307 while lineix < len(lines):
1308 if lines[lineix].strip().startswith('/*'):
1309 # Only return this marker if the comment goes beyond this line
1310 if lines[lineix].strip().find('*/', 2) < 0:
1311 return lineix
1312 lineix += 1
1313 return len(lines)
1314
1315
1316def FindNextMultiLineCommentEnd(lines, lineix):
1317 """We are inside a comment, find the end marker."""
1318 while lineix < len(lines):
1319 if lines[lineix].strip().endswith('*/'):
1320 return lineix
1321 lineix += 1
1322 return len(lines)
1323
1324
1325def RemoveMultiLineCommentsFromRange(lines, begin, end):
1326 """Clears a range of lines for multi-line comments."""
1327 # Having // dummy comments makes the lines non-empty, so we will not get
1328 # unnecessary blank line warnings later in the code.
1329 for i in range(begin, end):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001330 lines[i] = '/**/'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001331
1332
1333def RemoveMultiLineComments(filename, lines, error):
1334 """Removes multiline (c-style) comments from lines."""
1335 lineix = 0
1336 while lineix < len(lines):
1337 lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
1338 if lineix_begin >= len(lines):
1339 return
1340 lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
1341 if lineix_end >= len(lines):
1342 error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
1343 'Could not find end of multi-line comment')
1344 return
1345 RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
1346 lineix = lineix_end + 1
1347
1348
1349def CleanseComments(line):
1350 """Removes //-comments and single-line C-style /* */ comments.
1351
1352 Args:
1353 line: A line of C++ source.
1354
1355 Returns:
1356 The line with single-line comments removed.
1357 """
1358 commentpos = line.find('//')
1359 if commentpos != -1 and not IsCppString(line[:commentpos]):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00001360 line = line[:commentpos].rstrip()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001361 # get rid of /* ... */
1362 return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
1363
1364
erg@google.com6317a9c2009-06-25 00:28:19 +00001365class CleansedLines(object):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001366 """Holds 4 copies of all lines with different preprocessing applied to them.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001367
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001368 1) elided member contains lines without strings and comments.
1369 2) lines member contains lines without comments.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001370 3) raw_lines member contains all the lines without processing.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001371 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
1372 strings removed.
1373 All these members are of <type 'list'>, and of the same length.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001374 """
1375
1376 def __init__(self, lines):
1377 self.elided = []
1378 self.lines = []
1379 self.raw_lines = lines
1380 self.num_lines = len(lines)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001381 self.lines_without_raw_strings = CleanseRawStrings(lines)
1382 for linenum in range(len(self.lines_without_raw_strings)):
1383 self.lines.append(CleanseComments(
1384 self.lines_without_raw_strings[linenum]))
1385 elided = self._CollapseStrings(self.lines_without_raw_strings[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001386 self.elided.append(CleanseComments(elided))
1387
1388 def NumLines(self):
1389 """Returns the number of lines represented."""
1390 return self.num_lines
1391
1392 @staticmethod
1393 def _CollapseStrings(elided):
1394 """Collapses strings and chars on a line to simple "" or '' blocks.
1395
1396 We nix strings first so we're not fooled by text like '"http://"'
1397
1398 Args:
1399 elided: The line being processed.
1400
1401 Returns:
1402 The line with collapsed strings.
1403 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001404 if _RE_PATTERN_INCLUDE.match(elided):
1405 return elided
1406
1407 # Remove escaped characters first to make quote/single quote collapsing
1408 # basic. Things that look like escaped characters shouldn't occur
1409 # outside of strings and chars.
1410 elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
1411
1412 # Replace quoted strings and digit separators. Both single quotes
1413 # and double quotes are processed in the same loop, otherwise
1414 # nested quotes wouldn't work.
1415 collapsed = ''
1416 while True:
1417 # Find the first quote character
1418 match = Match(r'^([^\'"]*)([\'"])(.*)$', elided)
1419 if not match:
1420 collapsed += elided
1421 break
1422 head, quote, tail = match.groups()
1423
1424 if quote == '"':
1425 # Collapse double quoted strings
1426 second_quote = tail.find('"')
1427 if second_quote >= 0:
1428 collapsed += head + '""'
1429 elided = tail[second_quote + 1:]
1430 else:
1431 # Unmatched double quote, don't bother processing the rest
1432 # of the line since this is probably a multiline string.
1433 collapsed += elided
1434 break
1435 else:
1436 # Found single quote, check nearby text to eliminate digit separators.
1437 #
1438 # There is no special handling for floating point here, because
1439 # the integer/fractional/exponent parts would all be parsed
1440 # correctly as long as there are digits on both sides of the
1441 # separator. So we are fine as long as we don't see something
1442 # like "0.'3" (gcc 4.9.0 will not allow this literal).
1443 if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head):
1444 match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail)
1445 collapsed += head + match_literal.group(1).replace("'", '')
1446 elided = match_literal.group(2)
1447 else:
1448 second_quote = tail.find('\'')
1449 if second_quote >= 0:
1450 collapsed += head + "''"
1451 elided = tail[second_quote + 1:]
1452 else:
1453 # Unmatched single quote
1454 collapsed += elided
1455 break
1456
1457 return collapsed
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001458
1459
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001460def FindEndOfExpressionInLine(line, startpos, stack):
1461 """Find the position just after the end of current parenthesized expression.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001462
1463 Args:
1464 line: a CleansedLines line.
1465 startpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001466 stack: nesting stack at startpos.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001467
1468 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001469 On finding matching end: (index just after matching end, None)
1470 On finding an unclosed expression: (-1, None)
1471 Otherwise: (-1, new stack at end of this line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001472 """
1473 for i in xrange(startpos, len(line)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001474 char = line[i]
1475 if char in '([{':
1476 # Found start of parenthesized expression, push to expression stack
1477 stack.append(char)
1478 elif char == '<':
1479 # Found potential start of template argument list
1480 if i > 0 and line[i - 1] == '<':
1481 # Left shift operator
1482 if stack and stack[-1] == '<':
1483 stack.pop()
1484 if not stack:
1485 return (-1, None)
1486 elif i > 0 and Search(r'\boperator\s*$', line[0:i]):
1487 # operator<, don't add to stack
1488 continue
1489 else:
1490 # Tentative start of template argument list
1491 stack.append('<')
1492 elif char in ')]}':
1493 # Found end of parenthesized expression.
1494 #
1495 # If we are currently expecting a matching '>', the pending '<'
1496 # must have been an operator. Remove them from expression stack.
1497 while stack and stack[-1] == '<':
1498 stack.pop()
1499 if not stack:
1500 return (-1, None)
1501 if ((stack[-1] == '(' and char == ')') or
1502 (stack[-1] == '[' and char == ']') or
1503 (stack[-1] == '{' and char == '}')):
1504 stack.pop()
1505 if not stack:
1506 return (i + 1, None)
1507 else:
1508 # Mismatched parentheses
1509 return (-1, None)
1510 elif char == '>':
1511 # Found potential end of template argument list.
1512
1513 # Ignore "->" and operator functions
1514 if (i > 0 and
1515 (line[i - 1] == '-' or Search(r'\boperator\s*$', line[0:i - 1]))):
1516 continue
1517
1518 # Pop the stack if there is a matching '<'. Otherwise, ignore
1519 # this '>' since it must be an operator.
1520 if stack:
1521 if stack[-1] == '<':
1522 stack.pop()
1523 if not stack:
1524 return (i + 1, None)
1525 elif char == ';':
1526 # Found something that look like end of statements. If we are currently
1527 # expecting a '>', the matching '<' must have been an operator, since
1528 # template argument list should not contain statements.
1529 while stack and stack[-1] == '<':
1530 stack.pop()
1531 if not stack:
1532 return (-1, None)
1533
1534 # Did not find end of expression or unbalanced parentheses on this line
1535 return (-1, stack)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001536
1537
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001538def CloseExpression(clean_lines, linenum, pos):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001539 """If input points to ( or { or [ or <, finds the position that closes it.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001540
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001541 If lines[linenum][pos] points to a '(' or '{' or '[' or '<', finds the
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001542 linenum/pos that correspond to the closing of the expression.
1543
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001544 TODO(unknown): cpplint spends a fair bit of time matching parentheses.
1545 Ideally we would want to index all opening and closing parentheses once
1546 and have CloseExpression be just a simple lookup, but due to preprocessor
1547 tricks, this is not so easy.
1548
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001549 Args:
1550 clean_lines: A CleansedLines instance containing the file.
1551 linenum: The number of the line to check.
1552 pos: A position on the line.
1553
1554 Returns:
1555 A tuple (line, linenum, pos) pointer *past* the closing brace, or
1556 (line, len(lines), -1) if we never find a close. Note we ignore
1557 strings and comments when matching; and the line we return is the
1558 'cleansed' line at linenum.
1559 """
1560
1561 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001562 if (line[pos] not in '({[<') or Match(r'<[<=]', line[pos:]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001563 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001564
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001565 # Check first line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001566 (end_pos, stack) = FindEndOfExpressionInLine(line, pos, [])
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001567 if end_pos > -1:
1568 return (line, linenum, end_pos)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001569
1570 # Continue scanning forward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001571 while stack and linenum < clean_lines.NumLines() - 1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001572 linenum += 1
1573 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001574 (end_pos, stack) = FindEndOfExpressionInLine(line, 0, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001575 if end_pos > -1:
1576 return (line, linenum, end_pos)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001577
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001578 # Did not find end of expression before end of file, give up
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001579 return (line, clean_lines.NumLines(), -1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001580
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001581
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001582def FindStartOfExpressionInLine(line, endpos, stack):
1583 """Find position at the matching start of current expression.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001584
1585 This is almost the reverse of FindEndOfExpressionInLine, but note
1586 that the input position and returned position differs by 1.
1587
1588 Args:
1589 line: a CleansedLines line.
1590 endpos: start searching at this position.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001591 stack: nesting stack at endpos.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001592
1593 Returns:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001594 On finding matching start: (index at matching start, None)
1595 On finding an unclosed expression: (-1, None)
1596 Otherwise: (-1, new stack at beginning of this line)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001597 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001598 i = endpos
1599 while i >= 0:
1600 char = line[i]
1601 if char in ')]}':
1602 # Found end of expression, push to expression stack
1603 stack.append(char)
1604 elif char == '>':
1605 # Found potential end of template argument list.
1606 #
1607 # Ignore it if it's a "->" or ">=" or "operator>"
1608 if (i > 0 and
1609 (line[i - 1] == '-' or
1610 Match(r'\s>=\s', line[i - 1:]) or
1611 Search(r'\boperator\s*$', line[0:i]))):
1612 i -= 1
1613 else:
1614 stack.append('>')
1615 elif char == '<':
1616 # Found potential start of template argument list
1617 if i > 0 and line[i - 1] == '<':
1618 # Left shift operator
1619 i -= 1
1620 else:
1621 # If there is a matching '>', we can pop the expression stack.
1622 # Otherwise, ignore this '<' since it must be an operator.
1623 if stack and stack[-1] == '>':
1624 stack.pop()
1625 if not stack:
1626 return (i, None)
1627 elif char in '([{':
1628 # Found start of expression.
1629 #
1630 # If there are any unmatched '>' on the stack, they must be
1631 # operators. Remove those.
1632 while stack and stack[-1] == '>':
1633 stack.pop()
1634 if not stack:
1635 return (-1, None)
1636 if ((char == '(' and stack[-1] == ')') or
1637 (char == '[' and stack[-1] == ']') or
1638 (char == '{' and stack[-1] == '}')):
1639 stack.pop()
1640 if not stack:
1641 return (i, None)
1642 else:
1643 # Mismatched parentheses
1644 return (-1, None)
1645 elif char == ';':
1646 # Found something that look like end of statements. If we are currently
1647 # expecting a '<', the matching '>' must have been an operator, since
1648 # template argument list should not contain statements.
1649 while stack and stack[-1] == '>':
1650 stack.pop()
1651 if not stack:
1652 return (-1, None)
1653
1654 i -= 1
1655
1656 return (-1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001657
1658
1659def ReverseCloseExpression(clean_lines, linenum, pos):
1660 """If input points to ) or } or ] or >, finds the position that opens it.
1661
1662 If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1663 linenum/pos that correspond to the opening of the expression.
1664
1665 Args:
1666 clean_lines: A CleansedLines instance containing the file.
1667 linenum: The number of the line to check.
1668 pos: A position on the line.
1669
1670 Returns:
1671 A tuple (line, linenum, pos) pointer *at* the opening brace, or
1672 (line, 0, -1) if we never find the matching opening brace. Note
1673 we ignore strings and comments when matching; and the line we
1674 return is the 'cleansed' line at linenum.
1675 """
1676 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001677 if line[pos] not in ')}]>':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001678 return (line, 0, -1)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001679
1680 # Check last line
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001681 (start_pos, stack) = FindStartOfExpressionInLine(line, pos, [])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001682 if start_pos > -1:
1683 return (line, linenum, start_pos)
1684
1685 # Continue scanning backward
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001686 while stack and linenum > 0:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001687 linenum -= 1
1688 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001689 (start_pos, stack) = FindStartOfExpressionInLine(line, len(line) - 1, stack)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001690 if start_pos > -1:
1691 return (line, linenum, start_pos)
1692
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001693 # Did not find start of expression before beginning of file, give up
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001694 return (line, 0, -1)
1695
1696
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001697def CheckForCopyright(filename, lines, error):
1698 """Logs an error if no Copyright message appears at the top of the file."""
1699
1700 # We'll say it should occur by line 10. Don't forget there's a
1701 # dummy line at the front.
1702 for line in xrange(1, min(len(lines), 11)):
1703 if re.search(r'Copyright', lines[line], re.I): break
1704 else: # means no copyright line was found
1705 error(filename, 0, 'legal/copyright', 5,
1706 'No copyright message found. '
1707 'You should have a line: "Copyright [year] <Copyright Owner>"')
1708
1709
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001710def GetIndentLevel(line):
1711 """Return the number of leading spaces in line.
1712
1713 Args:
1714 line: A string to check.
1715
1716 Returns:
1717 An integer count of leading spaces, possibly zero.
1718 """
1719 indent = Match(r'^( *)\S', line)
1720 if indent:
1721 return len(indent.group(1))
1722 else:
1723 return 0
1724
1725
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001726def GetHeaderGuardCPPVariable(filename):
1727 """Returns the CPP variable that should be used as a header guard.
1728
1729 Args:
1730 filename: The name of a C++ header file.
1731
1732 Returns:
1733 The CPP variable that should be used as a header guard in the
1734 named file.
1735
1736 """
1737
erg@google.com35589e62010-11-17 18:58:16 +00001738 # Restores original filename in case that cpplint is invoked from Emacs's
1739 # flymake.
1740 filename = re.sub(r'_flymake\.h$', '.h', filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001741 filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001742 # Replace 'c++' with 'cpp'.
1743 filename = filename.replace('C++', 'cpp').replace('c++', 'cpp')
skym@chromium.org3990c412016-02-05 20:55:12 +00001744
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001745 fileinfo = FileInfo(filename)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00001746 file_path_from_root = fileinfo.RepositoryName()
1747 if _root:
1748 file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001749 return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001750
1751
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001752def CheckForHeaderGuard(filename, clean_lines, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001753 """Checks that the file contains a header guard.
1754
erg@google.com6317a9c2009-06-25 00:28:19 +00001755 Logs an error if no #ifndef header guard is present. For other
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001756 headers, checks that the full pathname is used.
1757
1758 Args:
1759 filename: The name of the C++ header file.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001760 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001761 error: The function to call with any errors found.
1762 """
1763
avakulenko@google.com59146752014-08-11 20:20:55 +00001764 # Don't check for header guards if there are error suppression
1765 # comments somewhere in this file.
1766 #
1767 # Because this is silencing a warning for a nonexistent line, we
1768 # only support the very specific NOLINT(build/header_guard) syntax,
1769 # and not the general NOLINT or NOLINT(*) syntax.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001770 raw_lines = clean_lines.lines_without_raw_strings
1771 for i in raw_lines:
avakulenko@google.com59146752014-08-11 20:20:55 +00001772 if Search(r'//\s*NOLINT\(build/header_guard\)', i):
1773 return
1774
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001775 cppvar = GetHeaderGuardCPPVariable(filename)
1776
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001777 ifndef = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001778 ifndef_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001779 define = ''
1780 endif = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001781 endif_linenum = 0
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001782 for linenum, line in enumerate(raw_lines):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001783 linesplit = line.split()
1784 if len(linesplit) >= 2:
1785 # find the first occurrence of #ifndef and #define, save arg
1786 if not ifndef and linesplit[0] == '#ifndef':
1787 # set ifndef to the header guard presented on the #ifndef line.
1788 ifndef = linesplit[1]
1789 ifndef_linenum = linenum
1790 if not define and linesplit[0] == '#define':
1791 define = linesplit[1]
1792 # find the last occurrence of #endif, save entire line
1793 if line.startswith('#endif'):
1794 endif = line
1795 endif_linenum = linenum
1796
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001797 if not ifndef or not define or ifndef != define:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001798 error(filename, 0, 'build/header_guard', 5,
1799 'No #ifndef header guard found, suggested CPP variable is: %s' %
1800 cppvar)
1801 return
1802
1803 # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
1804 # for backward compatibility.
erg@google.com35589e62010-11-17 18:58:16 +00001805 if ifndef != cppvar:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001806 error_level = 0
1807 if ifndef != cppvar + '_':
1808 error_level = 5
1809
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001810 ParseNolintSuppressions(filename, raw_lines[ifndef_linenum], ifndef_linenum,
erg@google.com35589e62010-11-17 18:58:16 +00001811 error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001812 error(filename, ifndef_linenum, 'build/header_guard', error_level,
1813 '#ifndef header guard has wrong style, please use: %s' % cppvar)
1814
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001815 # Check for "//" comments on endif line.
1816 ParseNolintSuppressions(filename, raw_lines[endif_linenum], endif_linenum,
1817 error)
1818 match = Match(r'#endif\s*//\s*' + cppvar + r'(_)?\b', endif)
1819 if match:
1820 if match.group(1) == '_':
1821 # Issue low severity warning for deprecated double trailing underscore
1822 error(filename, endif_linenum, 'build/header_guard', 0,
1823 '#endif line should be "#endif // %s"' % cppvar)
erg@chromium.orgc452fea2012-01-26 21:10:45 +00001824 return
1825
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001826 # Didn't find the corresponding "//" comment. If this file does not
1827 # contain any "//" comments at all, it could be that the compiler
1828 # only wants "/**/" comments, look for those instead.
1829 no_single_line_comments = True
1830 for i in xrange(1, len(raw_lines) - 1):
1831 line = raw_lines[i]
1832 if Match(r'^(?:(?:\'(?:\.|[^\'])*\')|(?:"(?:\.|[^"])*")|[^\'"])*//', line):
1833 no_single_line_comments = False
1834 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001835
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001836 if no_single_line_comments:
1837 match = Match(r'#endif\s*/\*\s*' + cppvar + r'(_)?\s*\*/', endif)
1838 if match:
1839 if match.group(1) == '_':
1840 # Low severity warning for double trailing underscore
1841 error(filename, endif_linenum, 'build/header_guard', 0,
1842 '#endif line should be "#endif /* %s */"' % cppvar)
1843 return
1844
1845 # Didn't find anything
1846 error(filename, endif_linenum, 'build/header_guard', 5,
1847 '#endif line should be "#endif // %s"' % cppvar)
1848
1849
1850def CheckHeaderFileIncluded(filename, include_state, error):
1851 """Logs an error if a .cc file does not include its header."""
1852
1853 # Do not check test files
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001854 fileinfo = FileInfo(filename)
1855 if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001856 return
1857
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00001858 headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h'
avakulenko@google.com255f2be2014-12-05 22:19:55 +00001859 if not os.path.exists(headerfile):
1860 return
1861 headername = FileInfo(headerfile).RepositoryName()
1862 first_include = 0
1863 for section_list in include_state.include_list:
1864 for f in section_list:
1865 if headername in f[0] or f[0] in headername:
1866 return
1867 if not first_include:
1868 first_include = f[1]
1869
1870 error(filename, first_include, 'build/include', 5,
1871 '%s should include its header file %s' % (fileinfo.RepositoryName(),
1872 headername))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001873
1874
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001875def CheckForBadCharacters(filename, lines, error):
1876 """Logs an error for each line containing bad characters.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001877
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001878 Two kinds of bad characters:
1879
1880 1. Unicode replacement characters: These indicate that either the file
1881 contained invalid UTF-8 (likely) or Unicode replacement characters (which
1882 it shouldn't). Note that it's possible for this to throw off line
1883 numbering if the invalid UTF-8 occurred adjacent to a newline.
1884
1885 2. NUL bytes. These are problematic for some tools.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001886
1887 Args:
1888 filename: The name of the current file.
1889 lines: An array of strings, each representing a line of the file.
1890 error: The function to call with any errors found.
1891 """
1892 for linenum, line in enumerate(lines):
1893 if u'\ufffd' in line:
1894 error(filename, linenum, 'readability/utf8', 5,
1895 'Line contains invalid UTF-8 (or Unicode replacement character).')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001896 if '\0' in line:
1897 error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001898
1899
1900def CheckForNewlineAtEOF(filename, lines, error):
1901 """Logs an error if there is no newline char at the end of the file.
1902
1903 Args:
1904 filename: The name of the current file.
1905 lines: An array of strings, each representing a line of the file.
1906 error: The function to call with any errors found.
1907 """
1908
1909 # The array lines() was created by adding two newlines to the
1910 # original file (go figure), then splitting on \n.
1911 # To verify that the file ends in \n, we just have to make sure the
1912 # last-but-two element of lines() exists and is empty.
1913 if len(lines) < 3 or lines[-2]:
1914 error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
1915 'Could not find a newline character at the end of the file.')
1916
1917
1918def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
1919 """Logs an error if we see /* ... */ or "..." that extend past one line.
1920
1921 /* ... */ comments are legit inside macros, for one line.
1922 Otherwise, we prefer // comments, so it's ok to warn about the
1923 other. Likewise, it's ok for strings to extend across multiple
1924 lines, as long as a line continuation character (backslash)
1925 terminates each line. Although not currently prohibited by the C++
1926 style guide, it's ugly and unnecessary. We don't do well with either
1927 in this lint program, so we warn about both.
1928
1929 Args:
1930 filename: The name of the current file.
1931 clean_lines: A CleansedLines instance containing the file.
1932 linenum: The number of the line to check.
1933 error: The function to call with any errors found.
1934 """
1935 line = clean_lines.elided[linenum]
1936
1937 # Remove all \\ (escaped backslashes) from the line. They are OK, and the
1938 # second (escaped) slash may trigger later \" detection erroneously.
1939 line = line.replace('\\\\', '')
1940
1941 if line.count('/*') > line.count('*/'):
1942 error(filename, linenum, 'readability/multiline_comment', 5,
1943 'Complex multi-line /*...*/-style comment found. '
1944 'Lint may give bogus warnings. '
1945 'Consider replacing these with //-style comments, '
1946 'with #if 0...#endif, '
1947 'or with more clearly structured multi-line comments.')
1948
1949 if (line.count('"') - line.count('\\"')) % 2:
1950 error(filename, linenum, 'readability/multiline_string', 5,
1951 'Multi-line string ("...") found. This lint script doesn\'t '
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00001952 'do well with such strings, and may give bogus warnings. '
1953 'Use C++11 raw strings or concatenation instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001954
1955
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00001956# (non-threadsafe name, thread-safe alternative, validation pattern)
1957#
1958# The validation pattern is used to eliminate false positives such as:
1959# _rand(); // false positive due to substring match.
1960# ->rand(); // some member function rand().
1961# ACMRandom rand(seed); // some variable named rand.
1962# ISAACRandom rand(); // another variable named rand.
1963#
1964# Basically we require the return value of these functions to be used
1965# in some expression context on the same line by matching on some
1966# operator before the function name. This eliminates constructors and
1967# member function calls.
1968_UNSAFE_FUNC_PREFIX = r'(?:[-+*/=%^&|(<]\s*|>\s+)'
1969_THREADING_LIST = (
1970 ('asctime(', 'asctime_r(', _UNSAFE_FUNC_PREFIX + r'asctime\([^)]+\)'),
1971 ('ctime(', 'ctime_r(', _UNSAFE_FUNC_PREFIX + r'ctime\([^)]+\)'),
1972 ('getgrgid(', 'getgrgid_r(', _UNSAFE_FUNC_PREFIX + r'getgrgid\([^)]+\)'),
1973 ('getgrnam(', 'getgrnam_r(', _UNSAFE_FUNC_PREFIX + r'getgrnam\([^)]+\)'),
1974 ('getlogin(', 'getlogin_r(', _UNSAFE_FUNC_PREFIX + r'getlogin\(\)'),
1975 ('getpwnam(', 'getpwnam_r(', _UNSAFE_FUNC_PREFIX + r'getpwnam\([^)]+\)'),
1976 ('getpwuid(', 'getpwuid_r(', _UNSAFE_FUNC_PREFIX + r'getpwuid\([^)]+\)'),
1977 ('gmtime(', 'gmtime_r(', _UNSAFE_FUNC_PREFIX + r'gmtime\([^)]+\)'),
1978 ('localtime(', 'localtime_r(', _UNSAFE_FUNC_PREFIX + r'localtime\([^)]+\)'),
1979 ('rand(', 'rand_r(', _UNSAFE_FUNC_PREFIX + r'rand\(\)'),
1980 ('strtok(', 'strtok_r(',
1981 _UNSAFE_FUNC_PREFIX + r'strtok\([^)]+\)'),
1982 ('ttyname(', 'ttyname_r(', _UNSAFE_FUNC_PREFIX + r'ttyname\([^)]+\)'),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00001983 )
1984
1985
1986def CheckPosixThreading(filename, clean_lines, linenum, error):
1987 """Checks for calls to thread-unsafe functions.
1988
1989 Much code has been originally written without consideration of
1990 multi-threading. Also, engineers are relying on their old experience;
1991 they have learned posix before threading extensions were added. These
1992 tests guide the engineers to use thread-safe functions (when using
1993 posix directly).
1994
1995 Args:
1996 filename: The name of the current file.
1997 clean_lines: A CleansedLines instance containing the file.
1998 linenum: The number of the line to check.
1999 error: The function to call with any errors found.
2000 """
2001 line = clean_lines.elided[linenum]
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002002 for single_thread_func, multithread_safe_func, pattern in _THREADING_LIST:
2003 # Additional pattern matching check to confirm that this is the
2004 # function we are looking for
2005 if Search(pattern, line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002006 error(filename, linenum, 'runtime/threadsafe_fn', 2,
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002007 'Consider using ' + multithread_safe_func +
2008 '...) instead of ' + single_thread_func +
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002009 '...) for improved thread safety.')
2010
2011
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002012def CheckVlogArguments(filename, clean_lines, linenum, error):
2013 """Checks that VLOG() is only used for defining a logging level.
2014
2015 For example, VLOG(2) is correct. VLOG(INFO), VLOG(WARNING), VLOG(ERROR), and
2016 VLOG(FATAL) are not.
2017
2018 Args:
2019 filename: The name of the current file.
2020 clean_lines: A CleansedLines instance containing the file.
2021 linenum: The number of the line to check.
2022 error: The function to call with any errors found.
2023 """
2024 line = clean_lines.elided[linenum]
2025 if Search(r'\bVLOG\((INFO|ERROR|WARNING|DFATAL|FATAL)\)', line):
2026 error(filename, linenum, 'runtime/vlog', 5,
2027 'VLOG() should be used with numeric verbosity level. '
2028 'Use LOG() if you want symbolic severity levels.')
2029
erg@google.com26970fa2009-11-17 18:07:32 +00002030# Matches invalid increment: *count++, which moves pointer instead of
erg@google.com6317a9c2009-06-25 00:28:19 +00002031# incrementing a value.
erg@google.com26970fa2009-11-17 18:07:32 +00002032_RE_PATTERN_INVALID_INCREMENT = re.compile(
erg@google.com6317a9c2009-06-25 00:28:19 +00002033 r'^\s*\*\w+(\+\+|--);')
2034
2035
2036def CheckInvalidIncrement(filename, clean_lines, linenum, error):
erg@google.com26970fa2009-11-17 18:07:32 +00002037 """Checks for invalid increment *count++.
erg@google.com6317a9c2009-06-25 00:28:19 +00002038
2039 For example following function:
2040 void increment_counter(int* count) {
2041 *count++;
2042 }
2043 is invalid, because it effectively does count++, moving pointer, and should
2044 be replaced with ++*count, (*count)++ or *count += 1.
2045
2046 Args:
2047 filename: The name of the current file.
2048 clean_lines: A CleansedLines instance containing the file.
2049 linenum: The number of the line to check.
2050 error: The function to call with any errors found.
2051 """
2052 line = clean_lines.elided[linenum]
erg@google.com26970fa2009-11-17 18:07:32 +00002053 if _RE_PATTERN_INVALID_INCREMENT.match(line):
erg@google.com6317a9c2009-06-25 00:28:19 +00002054 error(filename, linenum, 'runtime/invalid_increment', 5,
2055 'Changing pointer instead of value (or unused value of operator*).')
2056
2057
avakulenko@google.com59146752014-08-11 20:20:55 +00002058def IsMacroDefinition(clean_lines, linenum):
2059 if Search(r'^#define', clean_lines[linenum]):
2060 return True
2061
2062 if linenum > 0 and Search(r'\\$', clean_lines[linenum - 1]):
2063 return True
2064
2065 return False
2066
2067
2068def IsForwardClassDeclaration(clean_lines, linenum):
2069 return Match(r'^\s*(\btemplate\b)*.*class\s+\w+;\s*$', clean_lines[linenum])
2070
2071
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002072class _BlockInfo(object):
2073 """Stores information about a generic block of code."""
2074
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002075 def __init__(self, linenum, seen_open_brace):
2076 self.starting_linenum = linenum
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002077 self.seen_open_brace = seen_open_brace
2078 self.open_parentheses = 0
2079 self.inline_asm = _NO_ASM
avakulenko@google.com59146752014-08-11 20:20:55 +00002080 self.check_namespace_indentation = False
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002081
2082 def CheckBegin(self, filename, clean_lines, linenum, error):
2083 """Run checks that applies to text up to the opening brace.
2084
2085 This is mostly for checking the text after the class identifier
2086 and the "{", usually where the base class is specified. For other
2087 blocks, there isn't much to check, so we always pass.
2088
2089 Args:
2090 filename: The name of the current file.
2091 clean_lines: A CleansedLines instance containing the file.
2092 linenum: The number of the line to check.
2093 error: The function to call with any errors found.
2094 """
2095 pass
2096
2097 def CheckEnd(self, filename, clean_lines, linenum, error):
2098 """Run checks that applies to text after the closing brace.
2099
2100 This is mostly used for checking end of namespace comments.
2101
2102 Args:
2103 filename: The name of the current file.
2104 clean_lines: A CleansedLines instance containing the file.
2105 linenum: The number of the line to check.
2106 error: The function to call with any errors found.
2107 """
2108 pass
2109
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002110 def IsBlockInfo(self):
2111 """Returns true if this block is a _BlockInfo.
2112
2113 This is convenient for verifying that an object is an instance of
2114 a _BlockInfo, but not an instance of any of the derived classes.
2115
2116 Returns:
2117 True for this class, False for derived classes.
2118 """
2119 return self.__class__ == _BlockInfo
2120
2121
2122class _ExternCInfo(_BlockInfo):
2123 """Stores information about an 'extern "C"' block."""
2124
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002125 def __init__(self, linenum):
2126 _BlockInfo.__init__(self, linenum, True)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002127
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002128
2129class _ClassInfo(_BlockInfo):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002130 """Stores information about a class."""
2131
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002132 def __init__(self, name, class_or_struct, clean_lines, linenum):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002133 _BlockInfo.__init__(self, linenum, False)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002134 self.name = name
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002135 self.is_derived = False
avakulenko@google.com59146752014-08-11 20:20:55 +00002136 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002137 if class_or_struct == 'struct':
2138 self.access = 'public'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002139 self.is_struct = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002140 else:
2141 self.access = 'private'
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002142 self.is_struct = False
2143
2144 # Remember initial indentation level for this class. Using raw_lines here
2145 # instead of elided to account for leading comments.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002146 self.class_indent = GetIndentLevel(clean_lines.raw_lines[linenum])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002147
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002148 # Try to find the end of the class. This will be confused by things like:
2149 # class A {
2150 # } *x = { ...
2151 #
2152 # But it's still good enough for CheckSectionSpacing.
2153 self.last_line = 0
2154 depth = 0
2155 for i in range(linenum, clean_lines.NumLines()):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002156 line = clean_lines.elided[i]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002157 depth += line.count('{') - line.count('}')
2158 if not depth:
2159 self.last_line = i
2160 break
2161
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002162 def CheckBegin(self, filename, clean_lines, linenum, error):
2163 # Look for a bare ':'
2164 if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
2165 self.is_derived = True
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002166
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002167 def CheckEnd(self, filename, clean_lines, linenum, error):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002168 # If there is a DISALLOW macro, it should appear near the end of
2169 # the class.
2170 seen_last_thing_in_class = False
2171 for i in xrange(linenum - 1, self.starting_linenum, -1):
2172 match = Search(
2173 r'\b(DISALLOW_COPY_AND_ASSIGN|DISALLOW_IMPLICIT_CONSTRUCTORS)\(' +
2174 self.name + r'\)',
2175 clean_lines.elided[i])
2176 if match:
2177 if seen_last_thing_in_class:
2178 error(filename, i, 'readability/constructors', 3,
2179 match.group(1) + ' should be the last thing in the class')
2180 break
2181
2182 if not Match(r'^\s*$', clean_lines.elided[i]):
2183 seen_last_thing_in_class = True
2184
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002185 # Check that closing brace is aligned with beginning of the class.
2186 # Only do this if the closing brace is indented by only whitespaces.
2187 # This means we will not check single-line class definitions.
2188 indent = Match(r'^( *)\}', clean_lines.elided[linenum])
2189 if indent and len(indent.group(1)) != self.class_indent:
2190 if self.is_struct:
2191 parent = 'struct ' + self.name
2192 else:
2193 parent = 'class ' + self.name
2194 error(filename, linenum, 'whitespace/indent', 3,
2195 'Closing brace should be aligned with beginning of %s' % parent)
2196
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002197
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002198class _NamespaceInfo(_BlockInfo):
2199 """Stores information about a namespace."""
2200
2201 def __init__(self, name, linenum):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002202 _BlockInfo.__init__(self, linenum, False)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002203 self.name = name or ''
avakulenko@google.com59146752014-08-11 20:20:55 +00002204 self.check_namespace_indentation = True
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002205
2206 def CheckEnd(self, filename, clean_lines, linenum, error):
2207 """Check end of namespace comments."""
2208 line = clean_lines.raw_lines[linenum]
2209
2210 # Check how many lines is enclosed in this namespace. Don't issue
2211 # warning for missing namespace comments if there aren't enough
2212 # lines. However, do apply checks if there is already an end of
2213 # namespace comment and it's incorrect.
2214 #
2215 # TODO(unknown): We always want to check end of namespace comments
2216 # if a namespace is large, but sometimes we also want to apply the
2217 # check if a short namespace contained nontrivial things (something
2218 # other than forward declarations). There is currently no logic on
2219 # deciding what these nontrivial things are, so this check is
2220 # triggered by namespace size only, which works most of the time.
2221 if (linenum - self.starting_linenum < 10
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002222 and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002223 return
2224
2225 # Look for matching comment at end of namespace.
2226 #
2227 # Note that we accept C style "/* */" comments for terminating
2228 # namespaces, so that code that terminate namespaces inside
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002229 # preprocessor macros can be cpplint clean.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002230 #
2231 # We also accept stuff like "// end of namespace <name>." with the
2232 # period at the end.
2233 #
2234 # Besides these, we don't accept anything else, otherwise we might
2235 # get false negatives when existing comment is a substring of the
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002236 # expected namespace.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002237 if self.name:
2238 # Named namespace
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002239 if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
2240 re.escape(self.name) + r'[\*/\.\\\s]*$'),
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002241 line):
2242 error(filename, linenum, 'readability/namespace', 5,
2243 'Namespace should be terminated with "// namespace %s"' %
2244 self.name)
2245 else:
2246 # Anonymous namespace
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002247 if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002248 # If "// namespace anonymous" or "// anonymous namespace (more text)",
2249 # mention "// anonymous namespace" as an acceptable form
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002250 if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002251 error(filename, linenum, 'readability/namespace', 5,
2252 'Anonymous namespace should be terminated with "// namespace"'
2253 ' or "// anonymous namespace"')
2254 else:
2255 error(filename, linenum, 'readability/namespace', 5,
2256 'Anonymous namespace should be terminated with "// namespace"')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002257
2258
2259class _PreprocessorInfo(object):
2260 """Stores checkpoints of nesting stacks when #if/#else is seen."""
2261
2262 def __init__(self, stack_before_if):
2263 # The entire nesting stack before #if
2264 self.stack_before_if = stack_before_if
2265
2266 # The entire nesting stack up to #else
2267 self.stack_before_else = []
2268
2269 # Whether we have already seen #else or #elif
2270 self.seen_else = False
2271
2272
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002273class NestingState(object):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002274 """Holds states related to parsing braces."""
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002275
2276 def __init__(self):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002277 # Stack for tracking all braces. An object is pushed whenever we
2278 # see a "{", and popped when we see a "}". Only 3 types of
2279 # objects are possible:
2280 # - _ClassInfo: a class or struct.
2281 # - _NamespaceInfo: a namespace.
2282 # - _BlockInfo: some other type of block.
2283 self.stack = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002284
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002285 # Top of the previous stack before each Update().
2286 #
2287 # Because the nesting_stack is updated at the end of each line, we
2288 # had to do some convoluted checks to find out what is the current
2289 # scope at the beginning of the line. This check is simplified by
2290 # saving the previous top of nesting stack.
2291 #
2292 # We could save the full stack, but we only need the top. Copying
2293 # the full nesting stack would slow down cpplint by ~10%.
2294 self.previous_stack_top = []
2295
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002296 # Stack of _PreprocessorInfo objects.
2297 self.pp_stack = []
2298
2299 def SeenOpenBrace(self):
2300 """Check if we have seen the opening brace for the innermost block.
2301
2302 Returns:
2303 True if we have seen the opening brace, False if the innermost
2304 block is still expecting an opening brace.
2305 """
2306 return (not self.stack) or self.stack[-1].seen_open_brace
2307
2308 def InNamespaceBody(self):
2309 """Check if we are currently one level inside a namespace body.
2310
2311 Returns:
2312 True if top of the stack is a namespace block, False otherwise.
2313 """
2314 return self.stack and isinstance(self.stack[-1], _NamespaceInfo)
2315
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002316 def InExternC(self):
2317 """Check if we are currently one level inside an 'extern "C"' block.
2318
2319 Returns:
2320 True if top of the stack is an extern block, False otherwise.
2321 """
2322 return self.stack and isinstance(self.stack[-1], _ExternCInfo)
2323
2324 def InClassDeclaration(self):
2325 """Check if we are currently one level inside a class or struct declaration.
2326
2327 Returns:
2328 True if top of the stack is a class/struct, False otherwise.
2329 """
2330 return self.stack and isinstance(self.stack[-1], _ClassInfo)
2331
2332 def InAsmBlock(self):
2333 """Check if we are currently one level inside an inline ASM block.
2334
2335 Returns:
2336 True if the top of the stack is a block containing inline ASM.
2337 """
2338 return self.stack and self.stack[-1].inline_asm != _NO_ASM
2339
2340 def InTemplateArgumentList(self, clean_lines, linenum, pos):
2341 """Check if current position is inside template argument list.
2342
2343 Args:
2344 clean_lines: A CleansedLines instance containing the file.
2345 linenum: The number of the line to check.
2346 pos: position just after the suspected template argument.
2347 Returns:
2348 True if (linenum, pos) is inside template arguments.
2349 """
2350 while linenum < clean_lines.NumLines():
2351 # Find the earliest character that might indicate a template argument
2352 line = clean_lines.elided[linenum]
2353 match = Match(r'^[^{};=\[\]\.<>]*(.)', line[pos:])
2354 if not match:
2355 linenum += 1
2356 pos = 0
2357 continue
2358 token = match.group(1)
2359 pos += len(match.group(0))
2360
2361 # These things do not look like template argument list:
2362 # class Suspect {
2363 # class Suspect x; }
2364 if token in ('{', '}', ';'): return False
2365
2366 # These things look like template argument list:
2367 # template <class Suspect>
2368 # template <class Suspect = default_value>
2369 # template <class Suspect[]>
2370 # template <class Suspect...>
2371 if token in ('>', '=', '[', ']', '.'): return True
2372
2373 # Check if token is an unmatched '<'.
2374 # If not, move on to the next character.
2375 if token != '<':
2376 pos += 1
2377 if pos >= len(line):
2378 linenum += 1
2379 pos = 0
2380 continue
2381
2382 # We can't be sure if we just find a single '<', and need to
2383 # find the matching '>'.
2384 (_, end_line, end_pos) = CloseExpression(clean_lines, linenum, pos - 1)
2385 if end_pos < 0:
2386 # Not sure if template argument list or syntax error in file
2387 return False
2388 linenum = end_line
2389 pos = end_pos
2390 return False
2391
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002392 def UpdatePreprocessor(self, line):
2393 """Update preprocessor stack.
2394
2395 We need to handle preprocessors due to classes like this:
2396 #ifdef SWIG
2397 struct ResultDetailsPageElementExtensionPoint {
2398 #else
2399 struct ResultDetailsPageElementExtensionPoint : public Extension {
2400 #endif
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002401
2402 We make the following assumptions (good enough for most files):
2403 - Preprocessor condition evaluates to true from #if up to first
2404 #else/#elif/#endif.
2405
2406 - Preprocessor condition evaluates to false from #else/#elif up
2407 to #endif. We still perform lint checks on these lines, but
2408 these do not affect nesting stack.
2409
2410 Args:
2411 line: current line to check.
2412 """
2413 if Match(r'^\s*#\s*(if|ifdef|ifndef)\b', line):
2414 # Beginning of #if block, save the nesting stack here. The saved
2415 # stack will allow us to restore the parsing state in the #else case.
2416 self.pp_stack.append(_PreprocessorInfo(copy.deepcopy(self.stack)))
2417 elif Match(r'^\s*#\s*(else|elif)\b', line):
2418 # Beginning of #else block
2419 if self.pp_stack:
2420 if not self.pp_stack[-1].seen_else:
2421 # This is the first #else or #elif block. Remember the
2422 # whole nesting stack up to this point. This is what we
2423 # keep after the #endif.
2424 self.pp_stack[-1].seen_else = True
2425 self.pp_stack[-1].stack_before_else = copy.deepcopy(self.stack)
2426
2427 # Restore the stack to how it was before the #if
2428 self.stack = copy.deepcopy(self.pp_stack[-1].stack_before_if)
2429 else:
2430 # TODO(unknown): unexpected #else, issue warning?
2431 pass
2432 elif Match(r'^\s*#\s*endif\b', line):
2433 # End of #if or #else blocks.
2434 if self.pp_stack:
2435 # If we saw an #else, we will need to restore the nesting
2436 # stack to its former state before the #else, otherwise we
2437 # will just continue from where we left off.
2438 if self.pp_stack[-1].seen_else:
2439 # Here we can just use a shallow copy since we are the last
2440 # reference to it.
2441 self.stack = self.pp_stack[-1].stack_before_else
2442 # Drop the corresponding #if
2443 self.pp_stack.pop()
2444 else:
2445 # TODO(unknown): unexpected #endif, issue warning?
2446 pass
2447
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002448 # TODO(unknown): Update() is too long, but we will refactor later.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002449 def Update(self, filename, clean_lines, linenum, error):
2450 """Update nesting state with current line.
2451
2452 Args:
2453 filename: The name of the current file.
2454 clean_lines: A CleansedLines instance containing the file.
2455 linenum: The number of the line to check.
2456 error: The function to call with any errors found.
2457 """
2458 line = clean_lines.elided[linenum]
2459
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002460 # Remember top of the previous nesting stack.
2461 #
2462 # The stack is always pushed/popped and not modified in place, so
2463 # we can just do a shallow copy instead of copy.deepcopy. Using
2464 # deepcopy would slow down cpplint by ~28%.
2465 if self.stack:
2466 self.previous_stack_top = self.stack[-1]
2467 else:
2468 self.previous_stack_top = None
2469
2470 # Update pp_stack
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002471 self.UpdatePreprocessor(line)
2472
2473 # Count parentheses. This is to avoid adding struct arguments to
2474 # the nesting stack.
2475 if self.stack:
2476 inner_block = self.stack[-1]
2477 depth_change = line.count('(') - line.count(')')
2478 inner_block.open_parentheses += depth_change
2479
2480 # Also check if we are starting or ending an inline assembly block.
2481 if inner_block.inline_asm in (_NO_ASM, _END_ASM):
2482 if (depth_change != 0 and
2483 inner_block.open_parentheses == 1 and
2484 _MATCH_ASM.match(line)):
2485 # Enter assembly block
2486 inner_block.inline_asm = _INSIDE_ASM
2487 else:
2488 # Not entering assembly block. If previous line was _END_ASM,
2489 # we will now shift to _NO_ASM state.
2490 inner_block.inline_asm = _NO_ASM
2491 elif (inner_block.inline_asm == _INSIDE_ASM and
2492 inner_block.open_parentheses == 0):
2493 # Exit assembly block
2494 inner_block.inline_asm = _END_ASM
2495
2496 # Consume namespace declaration at the beginning of the line. Do
2497 # this in a loop so that we catch same line declarations like this:
2498 # namespace proto2 { namespace bridge { class MessageSet; } }
2499 while True:
2500 # Match start of namespace. The "\b\s*" below catches namespace
2501 # declarations even if it weren't followed by a whitespace, this
2502 # is so that we don't confuse our namespace checker. The
2503 # missing spaces will be flagged by CheckSpacing.
2504 namespace_decl_match = Match(r'^\s*namespace\b\s*([:\w]+)?(.*)$', line)
2505 if not namespace_decl_match:
2506 break
2507
2508 new_namespace = _NamespaceInfo(namespace_decl_match.group(1), linenum)
2509 self.stack.append(new_namespace)
2510
2511 line = namespace_decl_match.group(2)
2512 if line.find('{') != -1:
2513 new_namespace.seen_open_brace = True
2514 line = line[line.find('{') + 1:]
2515
2516 # Look for a class declaration in whatever is left of the line
2517 # after parsing namespaces. The regexp accounts for decorated classes
2518 # such as in:
2519 # class LOCKABLE API Object {
2520 # };
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002521 class_decl_match = Match(
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002522 r'^(\s*(?:template\s*<[\w\s<>,:]*>\s*)?'
2523 r'(class|struct)\s+(?:[A-Z_]+\s+)*(\w+(?:::\w+)*))'
2524 r'(.*)$', line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002525 if (class_decl_match and
2526 (not self.stack or self.stack[-1].open_parentheses == 0)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002527 # We do not want to accept classes that are actually template arguments:
2528 # template <class Ignore1,
2529 # class Ignore2 = Default<Args>,
2530 # template <Args> class Ignore3>
2531 # void Function() {};
2532 #
2533 # To avoid template argument cases, we scan forward and look for
2534 # an unmatched '>'. If we see one, assume we are inside a
2535 # template argument list.
2536 end_declaration = len(class_decl_match.group(1))
2537 if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration):
2538 self.stack.append(_ClassInfo(
2539 class_decl_match.group(3), class_decl_match.group(2),
2540 clean_lines, linenum))
2541 line = class_decl_match.group(4)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002542
2543 # If we have not yet seen the opening brace for the innermost block,
2544 # run checks here.
2545 if not self.SeenOpenBrace():
2546 self.stack[-1].CheckBegin(filename, clean_lines, linenum, error)
2547
2548 # Update access control if we are inside a class/struct
2549 if self.stack and isinstance(self.stack[-1], _ClassInfo):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002550 classinfo = self.stack[-1]
2551 access_match = Match(
2552 r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
2553 r':(?:[^:]|$)',
2554 line)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002555 if access_match:
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002556 classinfo.access = access_match.group(2)
2557
2558 # Check that access keywords are indented +1 space. Skip this
2559 # check if the keywords are not preceded by whitespaces.
2560 indent = access_match.group(1)
2561 if (len(indent) != classinfo.class_indent + 1 and
2562 Match(r'^\s*$', indent)):
2563 if classinfo.is_struct:
2564 parent = 'struct ' + classinfo.name
2565 else:
2566 parent = 'class ' + classinfo.name
2567 slots = ''
2568 if access_match.group(3):
2569 slots = access_match.group(3)
2570 error(filename, linenum, 'whitespace/indent', 3,
2571 '%s%s: should be indented +1 space inside %s' % (
2572 access_match.group(2), slots, parent))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002573
2574 # Consume braces or semicolons from what's left of the line
2575 while True:
2576 # Match first brace, semicolon, or closed parenthesis.
2577 matched = Match(r'^[^{;)}]*([{;)}])(.*)$', line)
2578 if not matched:
2579 break
2580
2581 token = matched.group(1)
2582 if token == '{':
2583 # If namespace or class hasn't seen a opening brace yet, mark
2584 # namespace/class head as complete. Push a new block onto the
2585 # stack otherwise.
2586 if not self.SeenOpenBrace():
2587 self.stack[-1].seen_open_brace = True
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002588 elif Match(r'^extern\s*"[^"]*"\s*\{', line):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002589 self.stack.append(_ExternCInfo(linenum))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002590 else:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002591 self.stack.append(_BlockInfo(linenum, True))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002592 if _MATCH_ASM.match(line):
2593 self.stack[-1].inline_asm = _BLOCK_ASM
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002594
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002595 elif token == ';' or token == ')':
2596 # If we haven't seen an opening brace yet, but we already saw
2597 # a semicolon, this is probably a forward declaration. Pop
2598 # the stack for these.
2599 #
2600 # Similarly, if we haven't seen an opening brace yet, but we
2601 # already saw a closing parenthesis, then these are probably
2602 # function arguments with extra "class" or "struct" keywords.
2603 # Also pop these stack for these.
2604 if not self.SeenOpenBrace():
2605 self.stack.pop()
2606 else: # token == '}'
2607 # Perform end of block checks and pop the stack.
2608 if self.stack:
2609 self.stack[-1].CheckEnd(filename, clean_lines, linenum, error)
2610 self.stack.pop()
2611 line = matched.group(2)
2612
2613 def InnermostClass(self):
2614 """Get class info on the top of the stack.
2615
2616 Returns:
2617 A _ClassInfo object if we are inside a class, or None otherwise.
2618 """
2619 for i in range(len(self.stack), 0, -1):
2620 classinfo = self.stack[i - 1]
2621 if isinstance(classinfo, _ClassInfo):
2622 return classinfo
2623 return None
2624
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002625 def CheckCompletedBlocks(self, filename, error):
2626 """Checks that all classes and namespaces have been completely parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002627
2628 Call this when all lines in a file have been processed.
2629 Args:
2630 filename: The name of the current file.
2631 error: The function to call with any errors found.
2632 """
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002633 # Note: This test can result in false positives if #ifdef constructs
2634 # get in the way of brace matching. See the testBuildClass test in
2635 # cpplint_unittest.py for an example of this.
2636 for obj in self.stack:
2637 if isinstance(obj, _ClassInfo):
2638 error(filename, obj.starting_linenum, 'build/class', 5,
2639 'Failed to find complete declaration of class %s' %
2640 obj.name)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002641 elif isinstance(obj, _NamespaceInfo):
2642 error(filename, obj.starting_linenum, 'build/namespaces', 5,
2643 'Failed to find complete declaration of namespace %s' %
2644 obj.name)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002645
2646
2647def CheckForNonStandardConstructs(filename, clean_lines, linenum,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002648 nesting_state, error):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002649 r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002650
2651 Complain about several constructs which gcc-2 accepts, but which are
2652 not standard C++. Warning about these in lint is one way to ease the
2653 transition to new compilers.
2654 - put storage class first (e.g. "static const" instead of "const static").
2655 - "%lld" instead of %qd" in printf-type functions.
2656 - "%1$d" is non-standard in printf-type functions.
2657 - "\%" is an undefined character escape sequence.
2658 - text after #endif is not allowed.
2659 - invalid inner-style forward declaration.
2660 - >? and <? operators, and their >?= and <?= cousins.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002661
erg@google.com26970fa2009-11-17 18:07:32 +00002662 Additionally, check for constructor/destructor style violations and reference
2663 members, as it is very convenient to do so while checking for
2664 gcc-2 compliance.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002665
2666 Args:
2667 filename: The name of the current file.
2668 clean_lines: A CleansedLines instance containing the file.
2669 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002670 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002671 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002672 error: A callable to which errors are reported, which takes 4 arguments:
2673 filename, line number, error level, and message
2674 """
2675
2676 # Remove comments from the line, but leave in strings for now.
2677 line = clean_lines.lines[linenum]
2678
2679 if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
2680 error(filename, linenum, 'runtime/printf_format', 3,
2681 '%q in format strings is deprecated. Use %ll instead.')
2682
2683 if Search(r'printf\s*\(.*".*%\d+\$', line):
2684 error(filename, linenum, 'runtime/printf_format', 2,
2685 '%N$ formats are unconventional. Try rewriting to avoid them.')
2686
2687 # Remove escaped backslashes before looking for undefined escapes.
2688 line = line.replace('\\\\', '')
2689
2690 if Search(r'("|\').*\\(%|\[|\(|{)', line):
2691 error(filename, linenum, 'build/printf_format', 3,
2692 '%, [, (, and { are undefined character escapes. Unescape them.')
2693
2694 # For the rest, work with both comments and strings removed.
2695 line = clean_lines.elided[linenum]
2696
2697 if Search(r'\b(const|volatile|void|char|short|int|long'
2698 r'|float|double|signed|unsigned'
2699 r'|schar|u?int8|u?int16|u?int32|u?int64)'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002700 r'\s+(register|static|extern|typedef)\b',
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002701 line):
2702 error(filename, linenum, 'build/storage_class', 5,
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002703 'Storage-class specifier (static, extern, typedef, etc) should be '
2704 'at the beginning of the declaration.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002705
2706 if Match(r'\s*#\s*endif\s*[^/\s]+', line):
2707 error(filename, linenum, 'build/endif_comment', 5,
2708 'Uncommented text after #endif is non-standard. Use a comment.')
2709
2710 if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
2711 error(filename, linenum, 'build/forward_decl', 5,
2712 'Inner-style forward declarations are invalid. Remove this line.')
2713
2714 if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
2715 line):
2716 error(filename, linenum, 'build/deprecated', 3,
2717 '>? and <? (max and min) operators are non-standard and deprecated.')
2718
erg@google.com26970fa2009-11-17 18:07:32 +00002719 if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
2720 # TODO(unknown): Could it be expanded safely to arbitrary references,
2721 # without triggering too many false positives? The first
2722 # attempt triggered 5 warnings for mostly benign code in the regtest, hence
2723 # the restriction.
2724 # Here's the original regexp, for the reference:
2725 # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
2726 # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
2727 error(filename, linenum, 'runtime/member_string_references', 2,
2728 'const string& members are dangerous. It is much better to use '
2729 'alternatives, such as pointers or simple constants.')
2730
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00002731 # Everything else in this function operates on class declarations.
2732 # Return early if the top of the nesting stack is not a class, or if
2733 # the class head is not completed yet.
2734 classinfo = nesting_state.InnermostClass()
2735 if not classinfo or not classinfo.seen_open_brace:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002736 return
2737
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002738 # The class may have been declared with namespace or classname qualifiers.
2739 # The constructor and destructor will not have those qualifiers.
2740 base_classname = classinfo.name.split('::')[-1]
2741
2742 # Look for single-argument constructors that aren't marked explicit.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002743 # Technically a valid construct, but against style.
avakulenko@google.com59146752014-08-11 20:20:55 +00002744 explicit_constructor_match = Match(
2745 r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*'
2746 r'\(((?:[^()]|\([^()]*\))*)\)'
2747 % re.escape(base_classname),
2748 line)
2749
2750 if explicit_constructor_match:
2751 is_marked_explicit = explicit_constructor_match.group(1)
2752
2753 if not explicit_constructor_match.group(2):
2754 constructor_args = []
2755 else:
2756 constructor_args = explicit_constructor_match.group(2).split(',')
2757
2758 # collapse arguments so that commas in template parameter lists and function
2759 # argument parameter lists don't split arguments in two
2760 i = 0
2761 while i < len(constructor_args):
2762 constructor_arg = constructor_args[i]
2763 while (constructor_arg.count('<') > constructor_arg.count('>') or
2764 constructor_arg.count('(') > constructor_arg.count(')')):
2765 constructor_arg += ',' + constructor_args[i + 1]
2766 del constructor_args[i + 1]
2767 constructor_args[i] = constructor_arg
2768 i += 1
2769
2770 defaulted_args = [arg for arg in constructor_args if '=' in arg]
2771 noarg_constructor = (not constructor_args or # empty arg list
2772 # 'void' arg specifier
2773 (len(constructor_args) == 1 and
2774 constructor_args[0].strip() == 'void'))
2775 onearg_constructor = ((len(constructor_args) == 1 and # exactly one arg
2776 not noarg_constructor) or
2777 # all but at most one arg defaulted
2778 (len(constructor_args) >= 1 and
2779 not noarg_constructor and
2780 len(defaulted_args) >= len(constructor_args) - 1))
2781 initializer_list_constructor = bool(
2782 onearg_constructor and
2783 Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
2784 copy_constructor = bool(
2785 onearg_constructor and
2786 Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
2787 % re.escape(base_classname), constructor_args[0].strip()))
2788
2789 if (not is_marked_explicit and
2790 onearg_constructor and
2791 not initializer_list_constructor and
2792 not copy_constructor):
2793 if defaulted_args:
2794 error(filename, linenum, 'runtime/explicit', 5,
2795 'Constructors callable with one argument '
2796 'should be marked explicit.')
2797 else:
2798 error(filename, linenum, 'runtime/explicit', 5,
2799 'Single-parameter constructors should be marked explicit.')
2800 elif is_marked_explicit and not onearg_constructor:
2801 if noarg_constructor:
2802 error(filename, linenum, 'runtime/explicit', 5,
2803 'Zero-parameter constructors should not be marked explicit.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002804
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002805
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002806def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002807 """Checks for the correctness of various spacing around function calls.
2808
2809 Args:
2810 filename: The name of the current file.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002811 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002812 linenum: The number of the line to check.
2813 error: The function to call with any errors found.
2814 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002815 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002816
2817 # Since function calls often occur inside if/for/while/switch
2818 # expressions - which have their own, more liberal conventions - we
2819 # first see if we should be looking inside such an expression for a
2820 # function call, to which we can apply more strict standards.
2821 fncall = line # if there's no control flow construct, look at whole line
2822 for pattern in (r'\bif\s*\((.*)\)\s*{',
2823 r'\bfor\s*\((.*)\)\s*{',
2824 r'\bwhile\s*\((.*)\)\s*[{;]',
2825 r'\bswitch\s*\((.*)\)\s*{'):
2826 match = Search(pattern, line)
2827 if match:
2828 fncall = match.group(1) # look inside the parens for function calls
2829 break
2830
2831 # Except in if/for/while/switch, there should never be space
2832 # immediately inside parens (eg "f( 3, 4 )"). We make an exception
2833 # for nested parens ( (a+b) + c ). Likewise, there should never be
2834 # a space before a ( when it's a function argument. I assume it's a
2835 # function argument when the char before the whitespace is legal in
2836 # a function name (alnum + _) and we're not starting a macro. Also ignore
2837 # pointers and references to arrays and functions coz they're too tricky:
2838 # we use a very simple way to recognize these:
2839 # " (something)(maybe-something)" or
2840 # " (something)(maybe-something," or
2841 # " (something)[something]"
2842 # Note that we assume the contents of [] to be short enough that
2843 # they'll never need to wrap.
2844 if ( # Ignore control structures.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00002845 not Search(r'\b(if|for|while|switch|return|new|delete|catch|sizeof)\b',
2846 fncall) and
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002847 # Ignore pointers/references to functions.
2848 not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
2849 # Ignore pointers/references to arrays.
2850 not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
erg@google.com6317a9c2009-06-25 00:28:19 +00002851 if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002852 error(filename, linenum, 'whitespace/parens', 4,
2853 'Extra space after ( in function call')
erg@google.com6317a9c2009-06-25 00:28:19 +00002854 elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002855 error(filename, linenum, 'whitespace/parens', 2,
2856 'Extra space after (')
2857 if (Search(r'\w\s+\(', fncall) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002858 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 +00002859 not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
avakulenko@google.com255f2be2014-12-05 22:19:55 +00002860 not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
2861 not Search(r'\bcase\s+\(', fncall)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002862 # TODO(unknown): Space after an operator function seem to be a common
2863 # error, silence those for now by restricting them to highest verbosity.
2864 if Search(r'\boperator_*\b', line):
2865 error(filename, linenum, 'whitespace/parens', 0,
2866 'Extra space before ( in function call')
2867 else:
2868 error(filename, linenum, 'whitespace/parens', 4,
2869 'Extra space before ( in function call')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002870 # If the ) is followed only by a newline or a { + newline, assume it's
2871 # part of a control statement (if/while/etc), and don't complain
2872 if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002873 # If the closing parenthesis is preceded by only whitespaces,
2874 # try to give a more descriptive error message.
2875 if Search(r'^\s+\)', fncall):
2876 error(filename, linenum, 'whitespace/parens', 2,
2877 'Closing ) should be moved to the previous line')
2878 else:
2879 error(filename, linenum, 'whitespace/parens', 2,
2880 'Extra space before )')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002881
2882
2883def IsBlankLine(line):
2884 """Returns true if the given line is blank.
2885
2886 We consider a line to be blank if the line is empty or consists of
2887 only white spaces.
2888
2889 Args:
2890 line: A line of a string.
2891
2892 Returns:
2893 True, if the given line is blank.
2894 """
2895 return not line or line.isspace()
2896
2897
avakulenko@google.com59146752014-08-11 20:20:55 +00002898def CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
2899 error):
2900 is_namespace_indent_item = (
2901 len(nesting_state.stack) > 1 and
2902 nesting_state.stack[-1].check_namespace_indentation and
2903 isinstance(nesting_state.previous_stack_top, _NamespaceInfo) and
2904 nesting_state.previous_stack_top == nesting_state.stack[-2])
2905
2906 if ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
2907 clean_lines.elided, line):
2908 CheckItemIndentationInNamespace(filename, clean_lines.elided,
2909 line, error)
2910
2911
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002912def CheckForFunctionLengths(filename, clean_lines, linenum,
2913 function_state, error):
2914 """Reports for long function bodies.
2915
2916 For an overview why this is done, see:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002917 https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002918
2919 Uses a simplistic algorithm assuming other style guidelines
2920 (especially spacing) are followed.
2921 Only checks unindented functions, so class members are unchecked.
2922 Trivial bodies are unchecked, so constructors with huge initializer lists
2923 may be missed.
2924 Blank/comment lines are not counted so as to avoid encouraging the removal
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00002925 of vertical space and comments just to get through a lint check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002926 NOLINT *on the last line of a function* disables this check.
2927
2928 Args:
2929 filename: The name of the current file.
2930 clean_lines: A CleansedLines instance containing the file.
2931 linenum: The number of the line to check.
2932 function_state: Current function name and lines in body so far.
2933 error: The function to call with any errors found.
2934 """
2935 lines = clean_lines.lines
2936 line = lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002937 joined_line = ''
2938
2939 starting_func = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002940 regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ...
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002941 match_result = Match(regexp, line)
2942 if match_result:
2943 # If the name is all caps and underscores, figure it's a macro and
2944 # ignore it, unless it's TEST or TEST_F.
2945 function_name = match_result.group(1).split()[-1]
2946 if function_name == 'TEST' or function_name == 'TEST_F' or (
2947 not Match(r'[A-Z_]+$', function_name)):
2948 starting_func = True
2949
2950 if starting_func:
2951 body_found = False
erg@google.com6317a9c2009-06-25 00:28:19 +00002952 for start_linenum in xrange(linenum, clean_lines.NumLines()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002953 start_line = lines[start_linenum]
2954 joined_line += ' ' + start_line.lstrip()
2955 if Search(r'(;|})', start_line): # Declarations and trivial functions
2956 body_found = True
2957 break # ... ignore
2958 elif Search(r'{', start_line):
2959 body_found = True
2960 function = Search(r'((\w|:)*)\(', line).group(1)
2961 if Match(r'TEST', function): # Handle TEST... macros
2962 parameter_regexp = Search(r'(\(.*\))', joined_line)
2963 if parameter_regexp: # Ignore bad syntax
2964 function += parameter_regexp.group(1)
2965 else:
2966 function += '()'
2967 function_state.Begin(function)
2968 break
2969 if not body_found:
erg@google.com6317a9c2009-06-25 00:28:19 +00002970 # No body for the function (or evidence of a non-function) was found.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002971 error(filename, linenum, 'readability/fn_size', 5,
2972 'Lint failed to find start of function body.')
2973 elif Match(r'^\}\s*$', line): # function end
erg@google.com35589e62010-11-17 18:58:16 +00002974 function_state.Check(error, filename, linenum)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002975 function_state.End()
2976 elif not Match(r'^\s*$', line):
2977 function_state.Count() # Count non-blank/non-comment lines.
2978
2979
2980_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
2981
2982
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002983def CheckComment(line, filename, linenum, next_line_start, error):
2984 """Checks for common mistakes in comments.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002985
2986 Args:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002987 line: The line in question.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002988 filename: The name of the current file.
2989 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002990 next_line_start: The first non-whitespace column of the next line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00002991 error: The function to call with any errors found.
2992 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002993 commentpos = line.find('//')
2994 if commentpos != -1:
2995 # Check if the // may be in quotes. If so, ignore it
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00002996 if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00002997 # Allow one space for new scopes, two spaces otherwise:
2998 if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
2999 ((commentpos >= 1 and
3000 line[commentpos-1] not in string.whitespace) or
3001 (commentpos >= 2 and
3002 line[commentpos-2] not in string.whitespace))):
3003 error(filename, linenum, 'whitespace/comments', 2,
3004 'At least two spaces is best between code and comments')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003005
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003006 # Checks for common mistakes in TODO comments.
3007 comment = line[commentpos:]
3008 match = _RE_PATTERN_TODO.match(comment)
3009 if match:
3010 # One whitespace is correct; zero whitespace is handled elsewhere.
3011 leading_whitespace = match.group(1)
3012 if len(leading_whitespace) > 1:
3013 error(filename, linenum, 'whitespace/todo', 2,
3014 'Too many spaces before TODO')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003015
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003016 username = match.group(2)
3017 if not username:
3018 error(filename, linenum, 'readability/todo', 2,
3019 'Missing username in TODO; it should look like '
3020 '"// TODO(my_username): Stuff."')
3021
3022 middle_whitespace = match.group(3)
3023 # Comparisons made explicit for correctness -- pylint: disable=g-explicit-bool-comparison
3024 if middle_whitespace != ' ' and middle_whitespace != '':
3025 error(filename, linenum, 'whitespace/todo', 2,
3026 'TODO(my_username) should be followed by a space')
3027
3028 # If the comment contains an alphanumeric character, there
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003029 # should be a space somewhere between it and the // unless
3030 # it's a /// or //! Doxygen comment.
3031 if (Match(r'//[^ ]*\w', comment) and
3032 not Match(r'(///|//\!)(\s+|$)', comment)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003033 error(filename, linenum, 'whitespace/comments', 4,
3034 'Should have a space between // and comment')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003035
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003036
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003037def CheckAccess(filename, clean_lines, linenum, nesting_state, error):
3038 """Checks for improper use of DISALLOW* macros.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003039
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003040 Args:
3041 filename: The name of the current file.
3042 clean_lines: A CleansedLines instance containing the file.
3043 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003044 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003045 the current stack of nested blocks being parsed.
3046 error: The function to call with any errors found.
3047 """
3048 line = clean_lines.elided[linenum] # get rid of comments and strings
3049
3050 matched = Match((r'\s*(DISALLOW_COPY_AND_ASSIGN|'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003051 r'DISALLOW_IMPLICIT_CONSTRUCTORS)'), line)
3052 if not matched:
3053 return
3054 if nesting_state.stack and isinstance(nesting_state.stack[-1], _ClassInfo):
3055 if nesting_state.stack[-1].access != 'private':
3056 error(filename, linenum, 'readability/constructors', 3,
3057 '%s must be in the private: section' % matched.group(1))
3058
3059 else:
3060 # Found DISALLOW* macro outside a class declaration, or perhaps it
3061 # was used inside a function when it should have been part of the
3062 # class declaration. We could issue a warning here, but it
3063 # probably resulted in a compiler error already.
3064 pass
3065
3066
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003067def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003068 """Checks for the correctness of various spacing issues in the code.
3069
3070 Things we check for: spaces around operators, spaces after
3071 if/for/while/switch, no spaces around parens in function calls, two
3072 spaces between code and comment, don't start a block with a blank
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003073 line, don't end a function with a blank line, don't add a blank line
3074 after public/protected/private, don't have too many blank lines in a row.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003075
3076 Args:
3077 filename: The name of the current file.
3078 clean_lines: A CleansedLines instance containing the file.
3079 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003080 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003081 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003082 error: The function to call with any errors found.
3083 """
3084
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003085 # Don't use "elided" lines here, otherwise we can't check commented lines.
3086 # Don't want to use "raw" either, because we don't want to check inside C++11
3087 # raw strings,
3088 raw = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003089 line = raw[linenum]
3090
3091 # Before nixing comments, check if the line is blank for no good
3092 # reason. This includes the first line after a block is opened, and
3093 # blank lines at the end of a function (ie, right before a line like '}'
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003094 #
3095 # Skip all the blank line checks if we are immediately inside a
3096 # namespace body. In other words, don't issue blank line warnings
3097 # for this block:
3098 # namespace {
3099 #
3100 # }
3101 #
3102 # A warning about missing end of namespace comments will be issued instead.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003103 #
3104 # Also skip blank line checks for 'extern "C"' blocks, which are formatted
3105 # like namespaces.
3106 if (IsBlankLine(line) and
3107 not nesting_state.InNamespaceBody() and
3108 not nesting_state.InExternC()):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003109 elided = clean_lines.elided
3110 prev_line = elided[linenum - 1]
3111 prevbrace = prev_line.rfind('{')
3112 # TODO(unknown): Don't complain if line before blank line, and line after,
3113 # both start with alnums and are indented the same amount.
3114 # This ignores whitespace at the start of a namespace block
3115 # because those are not usually indented.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003116 if prevbrace != -1 and prev_line[prevbrace:].find('}') == -1:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003117 # OK, we have a blank line at the start of a code block. Before we
3118 # complain, we check if it is an exception to the rule: The previous
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003119 # non-empty line has the parameters of a function header that are indented
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003120 # 4 spaces (because they did not fit in a 80 column line when placed on
3121 # the same line as the function name). We also check for the case where
3122 # the previous line is indented 6 spaces, which may happen when the
3123 # initializers of a constructor do not fit into a 80 column line.
3124 exception = False
3125 if Match(r' {6}\w', prev_line): # Initializer list?
3126 # We are looking for the opening column of initializer list, which
3127 # should be indented 4 spaces to cause 6 space indentation afterwards.
3128 search_position = linenum-2
3129 while (search_position >= 0
3130 and Match(r' {6}\w', elided[search_position])):
3131 search_position -= 1
3132 exception = (search_position >= 0
3133 and elided[search_position][:5] == ' :')
3134 else:
3135 # Search for the function arguments or an initializer list. We use a
3136 # simple heuristic here: If the line is indented 4 spaces; and we have a
3137 # closing paren, without the opening paren, followed by an opening brace
3138 # or colon (for initializer lists) we assume that it is the last line of
3139 # a function header. If we have a colon indented 4 spaces, it is an
3140 # initializer list.
3141 exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
3142 prev_line)
3143 or Match(r' {4}:', prev_line))
3144
3145 if not exception:
3146 error(filename, linenum, 'whitespace/blank_line', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003147 'Redundant blank line at the start of a code block '
3148 'should be deleted.')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003149 # Ignore blank lines at the end of a block in a long if-else
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003150 # chain, like this:
3151 # if (condition1) {
3152 # // Something followed by a blank line
3153 #
3154 # } else if (condition2) {
3155 # // Something else
3156 # }
3157 if linenum + 1 < clean_lines.NumLines():
3158 next_line = raw[linenum + 1]
3159 if (next_line
3160 and Match(r'\s*}', next_line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003161 and next_line.find('} else ') == -1):
3162 error(filename, linenum, 'whitespace/blank_line', 3,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003163 'Redundant blank line at the end of a code block '
3164 'should be deleted.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003165
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003166 matched = Match(r'\s*(public|protected|private):', prev_line)
3167 if matched:
3168 error(filename, linenum, 'whitespace/blank_line', 3,
3169 'Do not leave a blank line after "%s:"' % matched.group(1))
3170
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003171 # Next, check comments
3172 next_line_start = 0
3173 if linenum + 1 < clean_lines.NumLines():
3174 next_line = raw[linenum + 1]
3175 next_line_start = len(next_line) - len(next_line.lstrip())
3176 CheckComment(line, filename, linenum, next_line_start, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003177
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003178 # get rid of comments and strings
3179 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003180
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003181 # You shouldn't have spaces before your brackets, except maybe after
3182 # 'delete []' or 'return []() {};'
3183 if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
3184 error(filename, linenum, 'whitespace/braces', 5,
3185 'Extra space before [')
3186
3187 # In range-based for, we wanted spaces before and after the colon, but
3188 # not around "::" tokens that might appear.
3189 if (Search(r'for *\(.*[^:]:[^: ]', line) or
3190 Search(r'for *\(.*[^: ]:[^:]', line)):
3191 error(filename, linenum, 'whitespace/forcolon', 2,
3192 'Missing space around colon in range-based for loop')
3193
3194
3195def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3196 """Checks for horizontal spacing around operators.
3197
3198 Args:
3199 filename: The name of the current file.
3200 clean_lines: A CleansedLines instance containing the file.
3201 linenum: The number of the line to check.
3202 error: The function to call with any errors found.
3203 """
3204 line = clean_lines.elided[linenum]
3205
3206 # Don't try to do spacing checks for operator methods. Do this by
3207 # replacing the troublesome characters with something else,
3208 # preserving column position for all other characters.
3209 #
3210 # The replacement is done repeatedly to avoid false positives from
3211 # operators that call operators.
3212 while True:
3213 match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
3214 if match:
3215 line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
3216 else:
3217 break
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003218
3219 # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
3220 # Otherwise not. Note we only check for non-spaces on *both* sides;
3221 # sometimes people put non-spaces on one side when aligning ='s among
3222 # many lines (not that this is behavior that I approve of...)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003223 if ((Search(r'[\w.]=', line) or
3224 Search(r'=[\w.]', line))
3225 and not Search(r'\b(if|while|for) ', line)
3226 # Operators taken from [lex.operators] in C++11 standard.
3227 and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
3228 and not Search(r'operator=', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003229 error(filename, linenum, 'whitespace/operators', 4,
3230 'Missing spaces around =')
3231
3232 # It's ok not to have spaces around binary operators like + - * /, but if
3233 # there's too little whitespace, we get concerned. It's hard to tell,
3234 # though, so we punt on this one for now. TODO.
3235
3236 # You should always have whitespace around binary operators.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003237 #
3238 # Check <= and >= first to avoid false positives with < and >, then
3239 # check non-include lines for spacing around < and >.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003240 #
3241 # If the operator is followed by a comma, assume it's be used in a
3242 # macro context and don't do any checks. This avoids false
3243 # positives.
3244 #
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003245 # Note that && is not included here. This is because there are too
3246 # many false positives due to RValue references.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003247 match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003248 if match:
3249 error(filename, linenum, 'whitespace/operators', 3,
3250 'Missing spaces around %s' % match.group(1))
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003251 elif not Match(r'#.*include', line):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003252 # Look for < that is not surrounded by spaces. This is only
3253 # triggered if both sides are missing spaces, even though
3254 # technically should should flag if at least one side is missing a
3255 # space. This is done to avoid some false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003256 match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
3257 if match:
3258 (_, _, end_pos) = CloseExpression(
3259 clean_lines, linenum, len(match.group(1)))
3260 if end_pos <= -1:
3261 error(filename, linenum, 'whitespace/operators', 3,
3262 'Missing spaces around <')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003263
3264 # Look for > that is not surrounded by spaces. Similar to the
3265 # above, we only trigger if both sides are missing spaces to avoid
3266 # false positives with shifts.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003267 match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
3268 if match:
3269 (_, _, start_pos) = ReverseCloseExpression(
3270 clean_lines, linenum, len(match.group(1)))
3271 if start_pos <= -1:
3272 error(filename, linenum, 'whitespace/operators', 3,
3273 'Missing spaces around >')
3274
3275 # We allow no-spaces around << when used like this: 10<<20, but
3276 # not otherwise (particularly, not when used as streams)
avakulenko@google.com59146752014-08-11 20:20:55 +00003277 #
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003278 # We also allow operators following an opening parenthesis, since
3279 # those tend to be macros that deal with operators.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003280 match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003281 if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003282 not (match.group(1) == 'operator' and match.group(2) == ';')):
3283 error(filename, linenum, 'whitespace/operators', 3,
3284 'Missing spaces around <<')
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003285
3286 # We allow no-spaces around >> for almost anything. This is because
3287 # C++11 allows ">>" to close nested templates, which accounts for
3288 # most cases when ">>" is not followed by a space.
3289 #
3290 # We still warn on ">>" followed by alpha character, because that is
3291 # likely due to ">>" being used for right shifts, e.g.:
3292 # value >> alpha
3293 #
3294 # When ">>" is used to close templates, the alphanumeric letter that
3295 # follows would be part of an identifier, and there should still be
3296 # a space separating the template type and the identifier.
3297 # type<type<type>> alpha
3298 match = Search(r'>>[a-zA-Z_]', line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003299 if match:
3300 error(filename, linenum, 'whitespace/operators', 3,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003301 'Missing spaces around >>')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003302
3303 # There shouldn't be space around unary operators
3304 match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
3305 if match:
3306 error(filename, linenum, 'whitespace/operators', 4,
3307 'Extra space for operator %s' % match.group(1))
3308
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003309
3310def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
3311 """Checks for horizontal spacing around parentheses.
3312
3313 Args:
3314 filename: The name of the current file.
3315 clean_lines: A CleansedLines instance containing the file.
3316 linenum: The number of the line to check.
3317 error: The function to call with any errors found.
3318 """
3319 line = clean_lines.elided[linenum]
3320
3321 # No spaces after an if, while, switch, or for
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003322 match = Search(r' (if\(|for\(|while\(|switch\()', line)
3323 if match:
3324 error(filename, linenum, 'whitespace/parens', 5,
3325 'Missing space before ( in %s' % match.group(1))
3326
3327 # For if/for/while/switch, the left and right parens should be
3328 # consistent about how many spaces are inside the parens, and
3329 # there should either be zero or one spaces inside the parens.
3330 # We don't want: "if ( foo)" or "if ( foo )".
erg@google.com6317a9c2009-06-25 00:28:19 +00003331 # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003332 match = Search(r'\b(if|for|while|switch)\s*'
3333 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
3334 line)
3335 if match:
3336 if len(match.group(2)) != len(match.group(4)):
3337 if not (match.group(3) == ';' and
erg@google.com6317a9c2009-06-25 00:28:19 +00003338 len(match.group(2)) == 1 + len(match.group(4)) or
3339 not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003340 error(filename, linenum, 'whitespace/parens', 5,
3341 'Mismatching spaces inside () in %s' % match.group(1))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003342 if len(match.group(2)) not in [0, 1]:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003343 error(filename, linenum, 'whitespace/parens', 5,
3344 'Should have zero or one spaces inside ( and ) in %s' %
3345 match.group(1))
3346
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003347
3348def CheckCommaSpacing(filename, clean_lines, linenum, error):
3349 """Checks for horizontal spacing near commas and semicolons.
3350
3351 Args:
3352 filename: The name of the current file.
3353 clean_lines: A CleansedLines instance containing the file.
3354 linenum: The number of the line to check.
3355 error: The function to call with any errors found.
3356 """
3357 raw = clean_lines.lines_without_raw_strings
3358 line = clean_lines.elided[linenum]
3359
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003360 # 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 +00003361 #
3362 # This does not apply when the non-space character following the
3363 # comma is another comma, since the only time when that happens is
3364 # for empty macro arguments.
3365 #
3366 # We run this check in two passes: first pass on elided lines to
3367 # verify that lines contain missing whitespaces, second pass on raw
3368 # lines to confirm that those missing whitespaces are not due to
3369 # elided comments.
avakulenko@google.com59146752014-08-11 20:20:55 +00003370 if (Search(r',[^,\s]', ReplaceAll(r'\boperator\s*,\s*\(', 'F(', line)) and
3371 Search(r',[^,\s]', raw[linenum])):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003372 error(filename, linenum, 'whitespace/comma', 3,
3373 'Missing space after ,')
3374
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003375 # You should always have a space after a semicolon
3376 # except for few corner cases
3377 # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more
3378 # space after ;
3379 if Search(r';[^\s};\\)/]', line):
3380 error(filename, linenum, 'whitespace/semicolon', 3,
3381 'Missing space after ;')
3382
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003383
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003384def _IsType(clean_lines, nesting_state, expr):
3385 """Check if expression looks like a type name, returns true if so.
3386
3387 Args:
3388 clean_lines: A CleansedLines instance containing the file.
3389 nesting_state: A NestingState instance which maintains information about
3390 the current stack of nested blocks being parsed.
3391 expr: The expression to check.
3392 Returns:
3393 True, if token looks like a type.
3394 """
3395 # Keep only the last token in the expression
3396 last_word = Match(r'^.*(\b\S+)$', expr)
3397 if last_word:
3398 token = last_word.group(1)
3399 else:
3400 token = expr
3401
3402 # Match native types and stdint types
3403 if _TYPES.match(token):
3404 return True
3405
3406 # Try a bit harder to match templated types. Walk up the nesting
3407 # stack until we find something that resembles a typename
3408 # declaration for what we are looking for.
3409 typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) +
3410 r'\b')
3411 block_index = len(nesting_state.stack) - 1
3412 while block_index >= 0:
3413 if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
3414 return False
3415
3416 # Found where the opening brace is. We want to scan from this
3417 # line up to the beginning of the function, minus a few lines.
3418 # template <typename Type1, // stop scanning here
3419 # ...>
3420 # class C
3421 # : public ... { // start scanning here
3422 last_line = nesting_state.stack[block_index].starting_linenum
3423
3424 next_block_start = 0
3425 if block_index > 0:
3426 next_block_start = nesting_state.stack[block_index - 1].starting_linenum
3427 first_line = last_line
3428 while first_line >= next_block_start:
3429 if clean_lines.elided[first_line].find('template') >= 0:
3430 break
3431 first_line -= 1
3432 if first_line < next_block_start:
3433 # Didn't find any "template" keyword before reaching the next block,
3434 # there are probably no template things to check for this block
3435 block_index -= 1
3436 continue
3437
3438 # Look for typename in the specified range
3439 for i in xrange(first_line, last_line + 1, 1):
3440 if Search(typename_pattern, clean_lines.elided[i]):
3441 return True
3442 block_index -= 1
3443
3444 return False
3445
3446
3447def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003448 """Checks for horizontal spacing near commas.
3449
3450 Args:
3451 filename: The name of the current file.
3452 clean_lines: A CleansedLines instance containing the file.
3453 linenum: The number of the line to check.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003454 nesting_state: A NestingState instance which maintains information about
3455 the current stack of nested blocks being parsed.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003456 error: The function to call with any errors found.
3457 """
3458 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003459
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003460 # Except after an opening paren, or after another opening brace (in case of
3461 # an initializer list, for instance), you should have spaces before your
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003462 # braces when they are delimiting blocks, classes, namespaces etc.
3463 # And since you should never have braces at the beginning of a line,
3464 # this is an easy test. Except that braces used for initialization don't
3465 # follow the same rule; we often don't want spaces before those.
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003466 match = Match(r'^(.*[^ ({>]){', line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003467
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003468 if match:
3469 # Try a bit harder to check for brace initialization. This
3470 # happens in one of the following forms:
3471 # Constructor() : initializer_list_{} { ... }
3472 # Constructor{}.MemberFunction()
3473 # Type variable{};
3474 # FunctionCall(type{}, ...);
3475 # LastArgument(..., type{});
3476 # LOG(INFO) << type{} << " ...";
3477 # map_of_type[{...}] = ...;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003478 # ternary = expr ? new type{} : nullptr;
3479 # OuterTemplate<InnerTemplateConstructor<Type>{}>
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003480 #
3481 # We check for the character following the closing brace, and
3482 # silence the warning if it's one of those listed above, i.e.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003483 # "{.;,)<>]:".
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003484 #
3485 # To account for nested initializer list, we allow any number of
3486 # closing braces up to "{;,)<". We can't simply silence the
3487 # warning on first sight of closing brace, because that would
3488 # cause false negatives for things that are not initializer lists.
3489 # Silence this: But not this:
3490 # Outer{ if (...) {
3491 # Inner{...} if (...){ // Missing space before {
3492 # }; }
3493 #
3494 # There is a false negative with this approach if people inserted
3495 # spurious semicolons, e.g. "if (cond){};", but we will catch the
3496 # spurious semicolon with a separate check.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003497 leading_text = match.group(1)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003498 (endline, endlinenum, endpos) = CloseExpression(
3499 clean_lines, linenum, len(match.group(1)))
3500 trailing_text = ''
3501 if endpos > -1:
3502 trailing_text = endline[endpos:]
3503 for offset in xrange(endlinenum + 1,
3504 min(endlinenum + 3, clean_lines.NumLines() - 1)):
3505 trailing_text += clean_lines.elided[offset]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003506 # We also suppress warnings for `uint64_t{expression}` etc., as the style
3507 # guide recommends brace initialization for integral types to avoid
3508 # overflow/truncation.
3509 if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
3510 and not _IsType(clean_lines, nesting_state, leading_text)):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003511 error(filename, linenum, 'whitespace/braces', 5,
3512 'Missing space before {')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003513
3514 # Make sure '} else {' has spaces.
3515 if Search(r'}else', line):
3516 error(filename, linenum, 'whitespace/braces', 5,
3517 'Missing space before else')
3518
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003519 # You shouldn't have a space before a semicolon at the end of the line.
3520 # There's a special case for "for" since the style guide allows space before
3521 # the semicolon there.
3522 if Search(r':\s*;\s*$', line):
3523 error(filename, linenum, 'whitespace/semicolon', 5,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003524 'Semicolon defining empty statement. Use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003525 elif Search(r'^\s*;\s*$', line):
3526 error(filename, linenum, 'whitespace/semicolon', 5,
3527 'Line contains only semicolon. If this should be an empty statement, '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003528 'use {} instead.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003529 elif (Search(r'\s+;\s*$', line) and
3530 not Search(r'\bfor\b', line)):
3531 error(filename, linenum, 'whitespace/semicolon', 5,
3532 'Extra space before last semicolon. If this should be an empty '
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003533 'statement, use {} instead.')
3534
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003535
3536def IsDecltype(clean_lines, linenum, column):
3537 """Check if the token ending on (linenum, column) is decltype().
3538
3539 Args:
3540 clean_lines: A CleansedLines instance containing the file.
3541 linenum: the number of the line to check.
3542 column: end column of the token to check.
3543 Returns:
3544 True if this token is decltype() expression, False otherwise.
3545 """
3546 (text, _, start_col) = ReverseCloseExpression(clean_lines, linenum, column)
3547 if start_col < 0:
3548 return False
3549 if Search(r'\bdecltype\s*$', text[0:start_col]):
3550 return True
3551 return False
3552
3553
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003554def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
3555 """Checks for additional blank line issues related to sections.
3556
3557 Currently the only thing checked here is blank line before protected/private.
3558
3559 Args:
3560 filename: The name of the current file.
3561 clean_lines: A CleansedLines instance containing the file.
3562 class_info: A _ClassInfo objects.
3563 linenum: The number of the line to check.
3564 error: The function to call with any errors found.
3565 """
3566 # Skip checks if the class is small, where small means 25 lines or less.
3567 # 25 lines seems like a good cutoff since that's the usual height of
3568 # terminals, and any class that can't fit in one screen can't really
3569 # be considered "small".
3570 #
3571 # Also skip checks if we are on the first line. This accounts for
3572 # classes that look like
3573 # class Foo { public: ... };
3574 #
3575 # If we didn't find the end of the class, last_line would be zero,
3576 # and the check will be skipped by the first condition.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003577 if (class_info.last_line - class_info.starting_linenum <= 24 or
3578 linenum <= class_info.starting_linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003579 return
3580
3581 matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum])
3582 if matched:
3583 # Issue warning if the line before public/protected/private was
3584 # not a blank line, but don't do this if the previous line contains
3585 # "class" or "struct". This can happen two ways:
3586 # - We are at the beginning of the class.
3587 # - We are forward-declaring an inner class that is semantically
3588 # private, but needed to be public for implementation reasons.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003589 # Also ignores cases where the previous line ends with a backslash as can be
3590 # common when defining classes in C macros.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003591 prev_line = clean_lines.lines[linenum - 1]
3592 if (not IsBlankLine(prev_line) and
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003593 not Search(r'\b(class|struct)\b', prev_line) and
3594 not Search(r'\\$', prev_line)):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003595 # Try a bit harder to find the beginning of the class. This is to
3596 # account for multi-line base-specifier lists, e.g.:
3597 # class Derived
3598 # : public Base {
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003599 end_class_head = class_info.starting_linenum
3600 for i in range(class_info.starting_linenum, linenum):
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00003601 if Search(r'\{\s*$', clean_lines.lines[i]):
3602 end_class_head = i
3603 break
3604 if end_class_head < linenum - 1:
3605 error(filename, linenum, 'whitespace/blank_line', 3,
3606 '"%s:" should be preceded by a blank line' % matched.group(1))
3607
3608
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003609def GetPreviousNonBlankLine(clean_lines, linenum):
3610 """Return the most recent non-blank line and its line number.
3611
3612 Args:
3613 clean_lines: A CleansedLines instance containing the file contents.
3614 linenum: The number of the line to check.
3615
3616 Returns:
3617 A tuple with two elements. The first element is the contents of the last
3618 non-blank line before the current line, or the empty string if this is the
3619 first non-blank line. The second is the line number of that line, or -1
3620 if this is the first non-blank line.
3621 """
3622
3623 prevlinenum = linenum - 1
3624 while prevlinenum >= 0:
3625 prevline = clean_lines.elided[prevlinenum]
3626 if not IsBlankLine(prevline): # if not a blank line...
3627 return (prevline, prevlinenum)
3628 prevlinenum -= 1
3629 return ('', -1)
3630
3631
3632def CheckBraces(filename, clean_lines, linenum, error):
3633 """Looks for misplaced braces (e.g. at the end of line).
3634
3635 Args:
3636 filename: The name of the current file.
3637 clean_lines: A CleansedLines instance containing the file.
3638 linenum: The number of the line to check.
3639 error: The function to call with any errors found.
3640 """
3641
3642 line = clean_lines.elided[linenum] # get rid of comments and strings
3643
3644 if Match(r'\s*{\s*$', line):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003645 # We allow an open brace to start a line in the case where someone is using
3646 # braces in a block to explicitly create a new scope, which is commonly used
3647 # to control the lifetime of stack-allocated variables. Braces are also
3648 # used for brace initializers inside function calls. We don't detect this
3649 # perfectly: we just don't complain if the last non-whitespace character on
3650 # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003651 # previous line starts a preprocessor block. We also allow a brace on the
3652 # following line if it is part of an array initialization and would not fit
3653 # within the 80 character limit of the preceding line.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003654 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003655 if (not Search(r'[,;:}{(]\s*$', prevline) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003656 not Match(r'\s*#', prevline) and
3657 not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003658 error(filename, linenum, 'whitespace/braces', 4,
3659 '{ should almost always be at the end of the previous line')
3660
3661 # An else clause should be on the same line as the preceding closing brace.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003662 if Match(r'\s*else\b\s*(?:if\b|\{|$)', line):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003663 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3664 if Match(r'\s*}\s*$', prevline):
3665 error(filename, linenum, 'whitespace/newline', 4,
3666 'An else should appear on the same line as the preceding }')
3667
3668 # If braces come on one side of an else, they should be on both.
3669 # However, we have to worry about "else if" that spans multiple lines!
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003670 if Search(r'else if\s*\(', line): # could be multi-line if
3671 brace_on_left = bool(Search(r'}\s*else if\s*\(', line))
3672 # find the ( after the if
3673 pos = line.find('else if')
3674 pos = line.find('(', pos)
3675 if pos > 0:
3676 (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
3677 brace_on_right = endline[endpos:].find('{') != -1
3678 if brace_on_left != brace_on_right: # must be brace after if
3679 error(filename, linenum, 'readability/braces', 5,
3680 'If an else has a brace on one side, it should have it on both')
3681 elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
3682 error(filename, linenum, 'readability/braces', 5,
3683 'If an else has a brace on one side, it should have it on both')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003684
3685 # Likewise, an else should never have the else clause on the same line
3686 if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
3687 error(filename, linenum, 'whitespace/newline', 4,
3688 'Else clause should never be on same line as else (use 2 lines)')
3689
3690 # In the same way, a do/while should never be on one line
3691 if Match(r'\s*do [^\s{]', line):
3692 error(filename, linenum, 'whitespace/newline', 4,
3693 'do/while clauses should not be on a single line')
3694
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003695 # Check single-line if/else bodies. The style guide says 'curly braces are not
3696 # required for single-line statements'. We additionally allow multi-line,
3697 # single statements, but we reject anything with more than one semicolon in
3698 # it. This means that the first semicolon after the if should be at the end of
3699 # its line, and the line after that should have an indent level equal to or
3700 # lower than the if. We also check for ambiguous if/else nesting without
3701 # braces.
3702 if_else_match = Search(r'\b(if\s*\(|else\b)', line)
3703 if if_else_match and not Match(r'\s*#', line):
3704 if_indent = GetIndentLevel(line)
3705 endline, endlinenum, endpos = line, linenum, if_else_match.end()
3706 if_match = Search(r'\bif\s*\(', line)
3707 if if_match:
3708 # This could be a multiline if condition, so find the end first.
3709 pos = if_match.end() - 1
3710 (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos)
3711 # Check for an opening brace, either directly after the if or on the next
3712 # line. If found, this isn't a single-statement conditional.
3713 if (not Match(r'\s*{', endline[endpos:])
3714 and not (Match(r'\s*$', endline[endpos:])
3715 and endlinenum < (len(clean_lines.elided) - 1)
3716 and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))):
3717 while (endlinenum < len(clean_lines.elided)
3718 and ';' not in clean_lines.elided[endlinenum][endpos:]):
3719 endlinenum += 1
3720 endpos = 0
3721 if endlinenum < len(clean_lines.elided):
3722 endline = clean_lines.elided[endlinenum]
3723 # We allow a mix of whitespace and closing braces (e.g. for one-liner
3724 # methods) and a single \ after the semicolon (for macros)
3725 endpos = endline.find(';')
3726 if not Match(r';[\s}]*(\\?)$', endline[endpos:]):
avakulenko@google.com59146752014-08-11 20:20:55 +00003727 # Semicolon isn't the last character, there's something trailing.
3728 # Output a warning if the semicolon is not contained inside
3729 # a lambda expression.
3730 if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$',
3731 endline):
3732 error(filename, linenum, 'readability/braces', 4,
3733 'If/else bodies with multiple statements require braces')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003734 elif endlinenum < len(clean_lines.elided) - 1:
3735 # Make sure the next line is dedented
3736 next_line = clean_lines.elided[endlinenum + 1]
3737 next_indent = GetIndentLevel(next_line)
3738 # With ambiguous nested if statements, this will error out on the
3739 # if that *doesn't* match the else, regardless of whether it's the
3740 # inner one or outer one.
3741 if (if_match and Match(r'\s*else\b', next_line)
3742 and next_indent != if_indent):
3743 error(filename, linenum, 'readability/braces', 4,
3744 'Else clause should be indented at the same level as if. '
3745 'Ambiguous nested if/else chains require braces.')
3746 elif next_indent > if_indent:
3747 error(filename, linenum, 'readability/braces', 4,
3748 'If/else bodies with multiple statements require braces')
3749
3750
3751def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
3752 """Looks for redundant trailing semicolon.
3753
3754 Args:
3755 filename: The name of the current file.
3756 clean_lines: A CleansedLines instance containing the file.
3757 linenum: The number of the line to check.
3758 error: The function to call with any errors found.
3759 """
3760
3761 line = clean_lines.elided[linenum]
3762
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003763 # Block bodies should not be followed by a semicolon. Due to C++11
3764 # brace initialization, there are more places where semicolons are
3765 # required than not, so we use a whitelist approach to check these
3766 # rather than a blacklist. These are the places where "};" should
3767 # be replaced by just "}":
3768 # 1. Some flavor of block following closing parenthesis:
3769 # for (;;) {};
3770 # while (...) {};
3771 # switch (...) {};
3772 # Function(...) {};
3773 # if (...) {};
3774 # if (...) else if (...) {};
3775 #
3776 # 2. else block:
3777 # if (...) else {};
3778 #
3779 # 3. const member function:
3780 # Function(...) const {};
3781 #
3782 # 4. Block following some statement:
3783 # x = 42;
3784 # {};
3785 #
3786 # 5. Block at the beginning of a function:
3787 # Function(...) {
3788 # {};
3789 # }
3790 #
3791 # Note that naively checking for the preceding "{" will also match
3792 # braces inside multi-dimensional arrays, but this is fine since
3793 # that expression will not contain semicolons.
3794 #
3795 # 6. Block following another block:
3796 # while (true) {}
3797 # {};
3798 #
3799 # 7. End of namespaces:
3800 # namespace {};
3801 #
3802 # These semicolons seems far more common than other kinds of
3803 # redundant semicolons, possibly due to people converting classes
3804 # to namespaces. For now we do not warn for this case.
3805 #
3806 # Try matching case 1 first.
3807 match = Match(r'^(.*\)\s*)\{', line)
3808 if match:
3809 # Matched closing parenthesis (case 1). Check the token before the
3810 # matching opening parenthesis, and don't warn if it looks like a
3811 # macro. This avoids these false positives:
3812 # - macro that defines a base class
3813 # - multi-line macro that defines a base class
3814 # - macro that defines the whole class-head
3815 #
3816 # But we still issue warnings for macros that we know are safe to
3817 # warn, specifically:
3818 # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P
3819 # - TYPED_TEST
3820 # - INTERFACE_DEF
3821 # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED:
3822 #
3823 # We implement a whitelist of safe macros instead of a blacklist of
3824 # unsafe macros, even though the latter appears less frequently in
3825 # google code and would have been easier to implement. This is because
3826 # the downside for getting the whitelist wrong means some extra
3827 # semicolons, while the downside for getting the blacklist wrong
3828 # would result in compile errors.
3829 #
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003830 # In addition to macros, we also don't want to warn on
3831 # - Compound literals
3832 # - Lambdas
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003833 # - alignas specifier with anonymous structs
3834 # - decltype
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003835 closing_brace_pos = match.group(1).rfind(')')
3836 opening_parenthesis = ReverseCloseExpression(
3837 clean_lines, linenum, closing_brace_pos)
3838 if opening_parenthesis[2] > -1:
3839 line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003840 macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003841 func = Match(r'^(.*\])\s*$', line_prefix)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003842 if ((macro and
3843 macro.group(1) not in (
3844 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
3845 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
3846 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003847 (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
avakulenko@google.com255f2be2014-12-05 22:19:55 +00003848 Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003849 Search(r'\bdecltype$', line_prefix) or
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003850 Search(r'\s+=\s*$', line_prefix)):
3851 match = None
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003852 if (match and
3853 opening_parenthesis[1] > 1 and
3854 Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])):
3855 # Multi-line lambda-expression
3856 match = None
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003857
3858 else:
3859 # Try matching cases 2-3.
3860 match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line)
3861 if not match:
3862 # Try matching cases 4-6. These are always matched on separate lines.
3863 #
3864 # Note that we can't simply concatenate the previous line to the
3865 # current line and do a single match, otherwise we may output
3866 # duplicate warnings for the blank line case:
3867 # if (cond) {
3868 # // blank line
3869 # }
3870 prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3871 if prevline and Search(r'[;{}]\s*$', prevline):
3872 match = Match(r'^(\s*)\{', line)
3873
3874 # Check matching closing brace
3875 if match:
3876 (endline, endlinenum, endpos) = CloseExpression(
3877 clean_lines, linenum, len(match.group(1)))
3878 if endpos > -1 and Match(r'^\s*;', endline[endpos:]):
3879 # Current {} pair is eligible for semicolon check, and we have found
3880 # the redundant semicolon, output warning here.
3881 #
3882 # Note: because we are scanning forward for opening braces, and
3883 # outputting warnings for the matching closing brace, if there are
3884 # nested blocks with trailing semicolons, we will get the error
3885 # messages in reversed order.
3886 error(filename, endlinenum, 'readability/braces', 4,
3887 "You don't need a ; after a }")
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003888
3889
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003890def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
3891 """Look for empty loop/conditional body with only a single semicolon.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003892
3893 Args:
3894 filename: The name of the current file.
3895 clean_lines: A CleansedLines instance containing the file.
3896 linenum: The number of the line to check.
3897 error: The function to call with any errors found.
3898 """
3899
3900 # Search for loop keywords at the beginning of the line. Because only
3901 # whitespaces are allowed before the keywords, this will also ignore most
3902 # do-while-loops, since those lines should start with closing brace.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003903 #
3904 # We also check "if" blocks here, since an empty conditional block
3905 # is likely an error.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003906 line = clean_lines.elided[linenum]
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003907 matched = Match(r'\s*(for|while|if)\s*\(', line)
3908 if matched:
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003909 # Find the end of the conditional expression.
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00003910 (end_line, end_linenum, end_pos) = CloseExpression(
3911 clean_lines, linenum, line.find('('))
3912
3913 # Output warning if what follows the condition expression is a semicolon.
3914 # No warning for all other cases, including whitespace or newline, since we
3915 # have a separate check for semicolons preceded by whitespace.
3916 if end_pos >= 0 and Match(r';', end_line[end_pos:]):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00003917 if matched.group(1) == 'if':
3918 error(filename, end_linenum, 'whitespace/empty_conditional_body', 5,
3919 'Empty conditional bodies should use {}')
3920 else:
3921 error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
3922 'Empty loop bodies should use {} or continue')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003923
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00003924 # Check for if statements that have completely empty bodies (no comments)
3925 # and no else clauses.
3926 if end_pos >= 0 and matched.group(1) == 'if':
3927 # Find the position of the opening { for the if statement.
3928 # Return without logging an error if it has no brackets.
3929 opening_linenum = end_linenum
3930 opening_line_fragment = end_line[end_pos:]
3931 # Loop until EOF or find anything that's not whitespace or opening {.
3932 while not Search(r'^\s*\{', opening_line_fragment):
3933 if Search(r'^(?!\s*$)', opening_line_fragment):
3934 # Conditional has no brackets.
3935 return
3936 opening_linenum += 1
3937 if opening_linenum == len(clean_lines.elided):
3938 # Couldn't find conditional's opening { or any code before EOF.
3939 return
3940 opening_line_fragment = clean_lines.elided[opening_linenum]
3941 # Set opening_line (opening_line_fragment may not be entire opening line).
3942 opening_line = clean_lines.elided[opening_linenum]
3943
3944 # Find the position of the closing }.
3945 opening_pos = opening_line_fragment.find('{')
3946 if opening_linenum == end_linenum:
3947 # We need to make opening_pos relative to the start of the entire line.
3948 opening_pos += end_pos
3949 (closing_line, closing_linenum, closing_pos) = CloseExpression(
3950 clean_lines, opening_linenum, opening_pos)
3951 if closing_pos < 0:
3952 return
3953
3954 # Now construct the body of the conditional. This consists of the portion
3955 # of the opening line after the {, all lines until the closing line,
3956 # and the portion of the closing line before the }.
3957 if (clean_lines.raw_lines[opening_linenum] !=
3958 CleanseComments(clean_lines.raw_lines[opening_linenum])):
3959 # Opening line ends with a comment, so conditional isn't empty.
3960 return
3961 if closing_linenum > opening_linenum:
3962 # Opening line after the {. Ignore comments here since we checked above.
3963 body = list(opening_line[opening_pos+1:])
3964 # All lines until closing line, excluding closing line, with comments.
3965 body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
3966 # Closing line before the }. Won't (and can't) have comments.
3967 body.append(clean_lines.elided[closing_linenum][:closing_pos-1])
3968 body = '\n'.join(body)
3969 else:
3970 # If statement has brackets and fits on a single line.
3971 body = opening_line[opening_pos+1:closing_pos-1]
3972
3973 # Check if the body is empty
3974 if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
3975 return
3976 # The body is empty. Now make sure there's not an else clause.
3977 current_linenum = closing_linenum
3978 current_line_fragment = closing_line[closing_pos:]
3979 # Loop until EOF or find anything that's not whitespace or else clause.
3980 while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
3981 if Search(r'^(?=\s*else)', current_line_fragment):
3982 # Found an else clause, so don't log an error.
3983 return
3984 current_linenum += 1
3985 if current_linenum == len(clean_lines.elided):
3986 break
3987 current_line_fragment = clean_lines.elided[current_linenum]
3988
3989 # The body is empty and there's no else clause until EOF or other code.
3990 error(filename, end_linenum, 'whitespace/empty_if_body', 4,
3991 ('If statement had no body and no else clause'))
3992
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00003993
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00003994def FindCheckMacro(line):
3995 """Find a replaceable CHECK-like macro.
3996
3997 Args:
3998 line: line to search on.
3999 Returns:
4000 (macro name, start position), or (None, -1) if no replaceable
4001 macro is found.
4002 """
4003 for macro in _CHECK_MACROS:
4004 i = line.find(macro)
4005 if i >= 0:
4006 # Find opening parenthesis. Do a regular expression match here
4007 # to make sure that we are matching the expected CHECK macro, as
4008 # opposed to some other macro that happens to contain the CHECK
4009 # substring.
4010 matched = Match(r'^(.*\b' + macro + r'\s*)\(', line)
4011 if not matched:
4012 continue
4013 return (macro, len(matched.group(1)))
4014 return (None, -1)
4015
4016
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004017def CheckCheck(filename, clean_lines, linenum, error):
4018 """Checks the use of CHECK and EXPECT macros.
4019
4020 Args:
4021 filename: The name of the current file.
4022 clean_lines: A CleansedLines instance containing the file.
4023 linenum: The number of the line to check.
4024 error: The function to call with any errors found.
4025 """
4026
4027 # Decide the set of replacement macros that should be suggested
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004028 lines = clean_lines.elided
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004029 (check_macro, start_pos) = FindCheckMacro(lines[linenum])
4030 if not check_macro:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004031 return
4032
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004033 # Find end of the boolean expression by matching parentheses
4034 (last_line, end_line, end_pos) = CloseExpression(
4035 clean_lines, linenum, start_pos)
4036 if end_pos < 0:
4037 return
avakulenko@google.com59146752014-08-11 20:20:55 +00004038
4039 # If the check macro is followed by something other than a
4040 # semicolon, assume users will log their own custom error messages
4041 # and don't suggest any replacements.
4042 if not Match(r'\s*;', last_line[end_pos:]):
4043 return
4044
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004045 if linenum == end_line:
4046 expression = lines[linenum][start_pos + 1:end_pos - 1]
4047 else:
4048 expression = lines[linenum][start_pos + 1:]
4049 for i in xrange(linenum + 1, end_line):
4050 expression += lines[i]
4051 expression += last_line[0:end_pos - 1]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004052
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004053 # Parse expression so that we can take parentheses into account.
4054 # This avoids false positives for inputs like "CHECK((a < 4) == b)",
4055 # which is not replaceable by CHECK_LE.
4056 lhs = ''
4057 rhs = ''
4058 operator = None
4059 while expression:
4060 matched = Match(r'^\s*(<<|<<=|>>|>>=|->\*|->|&&|\|\||'
4061 r'==|!=|>=|>|<=|<|\()(.*)$', expression)
4062 if matched:
4063 token = matched.group(1)
4064 if token == '(':
4065 # Parenthesized operand
4066 expression = matched.group(2)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004067 (end, _) = FindEndOfExpressionInLine(expression, 0, ['('])
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004068 if end < 0:
4069 return # Unmatched parenthesis
4070 lhs += '(' + expression[0:end]
4071 expression = expression[end:]
4072 elif token in ('&&', '||'):
4073 # Logical and/or operators. This means the expression
4074 # contains more than one term, for example:
4075 # CHECK(42 < a && a < b);
4076 #
4077 # These are not replaceable with CHECK_LE, so bail out early.
4078 return
4079 elif token in ('<<', '<<=', '>>', '>>=', '->*', '->'):
4080 # Non-relational operator
4081 lhs += token
4082 expression = matched.group(2)
4083 else:
4084 # Relational operator
4085 operator = token
4086 rhs = matched.group(2)
4087 break
4088 else:
4089 # Unparenthesized operand. Instead of appending to lhs one character
4090 # at a time, we do another regular expression match to consume several
4091 # characters at once if possible. Trivial benchmark shows that this
4092 # is more efficient when the operands are longer than a single
4093 # character, which is generally the case.
4094 matched = Match(r'^([^-=!<>()&|]+)(.*)$', expression)
4095 if not matched:
4096 matched = Match(r'^(\s*\S)(.*)$', expression)
4097 if not matched:
4098 break
4099 lhs += matched.group(1)
4100 expression = matched.group(2)
4101
4102 # Only apply checks if we got all parts of the boolean expression
4103 if not (lhs and operator and rhs):
4104 return
4105
4106 # Check that rhs do not contain logical operators. We already know
4107 # that lhs is fine since the loop above parses out && and ||.
4108 if rhs.find('&&') > -1 or rhs.find('||') > -1:
4109 return
4110
4111 # At least one of the operands must be a constant literal. This is
4112 # to avoid suggesting replacements for unprintable things like
4113 # CHECK(variable != iterator)
4114 #
4115 # The following pattern matches decimal, hex integers, strings, and
4116 # characters (in that order).
4117 lhs = lhs.strip()
4118 rhs = rhs.strip()
4119 match_constant = r'^([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')$'
4120 if Match(match_constant, lhs) or Match(match_constant, rhs):
4121 # Note: since we know both lhs and rhs, we can provide a more
4122 # descriptive error message like:
4123 # Consider using CHECK_EQ(x, 42) instead of CHECK(x == 42)
4124 # Instead of:
4125 # Consider using CHECK_EQ instead of CHECK(a == b)
4126 #
4127 # We are still keeping the less descriptive message because if lhs
4128 # or rhs gets long, the error message might become unreadable.
4129 error(filename, linenum, 'readability/check', 2,
4130 'Consider using %s instead of %s(a %s b)' % (
4131 _CHECK_REPLACEMENT[check_macro][operator],
4132 check_macro, operator))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004133
4134
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004135def CheckAltTokens(filename, clean_lines, linenum, error):
4136 """Check alternative keywords being used in boolean expressions.
4137
4138 Args:
4139 filename: The name of the current file.
4140 clean_lines: A CleansedLines instance containing the file.
4141 linenum: The number of the line to check.
4142 error: The function to call with any errors found.
4143 """
4144 line = clean_lines.elided[linenum]
4145
4146 # Avoid preprocessor lines
4147 if Match(r'^\s*#', line):
4148 return
4149
4150 # Last ditch effort to avoid multi-line comments. This will not help
4151 # if the comment started before the current line or ended after the
4152 # current line, but it catches most of the false positives. At least,
4153 # it provides a way to workaround this warning for people who use
4154 # multi-line comments in preprocessor macros.
4155 #
4156 # TODO(unknown): remove this once cpplint has better support for
4157 # multi-line comments.
4158 if line.find('/*') >= 0 or line.find('*/') >= 0:
4159 return
4160
4161 for match in _ALT_TOKEN_REPLACEMENT_PATTERN.finditer(line):
4162 error(filename, linenum, 'readability/alt_tokens', 2,
4163 'Use operator %s instead of %s' % (
4164 _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
4165
4166
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004167def GetLineWidth(line):
4168 """Determines the width of the line in column positions.
4169
4170 Args:
4171 line: A string, which may be a Unicode string.
4172
4173 Returns:
4174 The width of the line in column positions, accounting for Unicode
4175 combining characters and wide characters.
4176 """
4177 if isinstance(line, unicode):
4178 width = 0
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004179 for uc in unicodedata.normalize('NFC', line):
4180 if unicodedata.east_asian_width(uc) in ('W', 'F'):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004181 width += 2
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004182 elif not unicodedata.combining(uc):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004183 width += 1
4184 return width
4185 else:
4186 return len(line)
4187
4188
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004189def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004190 error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004191 """Checks rules from the 'C++ style rules' section of cppguide.html.
4192
4193 Most of these rules are hard to test (naming, comment style), but we
4194 do what we can. In particular we check for 2-space indents, line lengths,
4195 tab usage, spaces inside code, etc.
4196
4197 Args:
4198 filename: The name of the current file.
4199 clean_lines: A CleansedLines instance containing the file.
4200 linenum: The number of the line to check.
4201 file_extension: The extension (without the dot) of the filename.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004202 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004203 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004204 error: The function to call with any errors found.
4205 """
4206
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004207 # Don't use "elided" lines here, otherwise we can't check commented lines.
4208 # Don't want to use "raw" either, because we don't want to check inside C++11
4209 # raw strings,
4210 raw_lines = clean_lines.lines_without_raw_strings
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004211 line = raw_lines[linenum]
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004212 prev = raw_lines[linenum - 1] if linenum > 0 else ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004213
4214 if line.find('\t') != -1:
4215 error(filename, linenum, 'whitespace/tab', 1,
4216 'Tab found; better to use spaces')
4217
4218 # One or three blank spaces at the beginning of the line is weird; it's
4219 # hard to reconcile that with 2-space indents.
4220 # NOTE: here are the conditions rob pike used for his tests. Mine aren't
4221 # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces
4222 # if(RLENGTH > 20) complain = 0;
4223 # if(match($0, " +(error|private|public|protected):")) complain = 0;
4224 # if(match(prev, "&& *$")) complain = 0;
4225 # if(match(prev, "\\|\\| *$")) complain = 0;
4226 # if(match(prev, "[\",=><] *$")) complain = 0;
4227 # if(match($0, " <<")) complain = 0;
4228 # if(match(prev, " +for \\(")) complain = 0;
4229 # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004230 scope_or_label_pattern = r'\s*\w+\s*:\s*\\?$'
4231 classinfo = nesting_state.InnermostClass()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004232 initial_spaces = 0
4233 cleansed_line = clean_lines.elided[linenum]
4234 while initial_spaces < len(line) and line[initial_spaces] == ' ':
4235 initial_spaces += 1
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004236 # There are certain situations we allow one space, notably for
4237 # section labels, and also lines containing multi-line raw strings.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004238 # We also don't check for lines that look like continuation lines
4239 # (of lines ending in double quotes, commas, equals, or angle brackets)
4240 # because the rules for how to indent those are non-trivial.
4241 if (not Search(r'[",=><] *$', prev) and
4242 (initial_spaces == 1 or initial_spaces == 3) and
4243 not Match(scope_or_label_pattern, cleansed_line) and
4244 not (clean_lines.raw_lines[linenum] != line and
4245 Match(r'^\s*""', line))):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004246 error(filename, linenum, 'whitespace/indent', 3,
4247 'Weird number of spaces at line-start. '
4248 'Are you using a 2-space indent?')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004249
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004250 if line and line[-1].isspace():
4251 error(filename, linenum, 'whitespace/end_of_line', 4,
4252 'Line ends in whitespace. Consider deleting these extra spaces.')
4253
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004254 # Check if the line is a header guard.
4255 is_header_guard = False
4256 if file_extension == 'h':
4257 cppvar = GetHeaderGuardCPPVariable(filename)
4258 if (line.startswith('#ifndef %s' % cppvar) or
4259 line.startswith('#define %s' % cppvar) or
4260 line.startswith('#endif // %s' % cppvar)):
4261 is_header_guard = True
4262 # #include lines and header guards can be long, since there's no clean way to
4263 # split them.
erg@google.com6317a9c2009-06-25 00:28:19 +00004264 #
4265 # URLs can be long too. It's possible to split these, but it makes them
4266 # harder to cut&paste.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004267 #
4268 # The "$Id:...$" comment may also get very long without it being the
4269 # developers fault.
erg@google.com6317a9c2009-06-25 00:28:19 +00004270 if (not line.startswith('#include') and not is_header_guard and
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004271 not Match(r'^\s*//.*http(s?)://\S*$', line) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004272 not Match(r'^\s*//\s*[^\s]*$', line) and
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004273 not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004274 line_width = GetLineWidth(line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004275 if line_width > _line_length:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004276 error(filename, linenum, 'whitespace/line_length', 2,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004277 'Lines should be <= %i characters long' % _line_length)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004278
4279 if (cleansed_line.count(';') > 1 and
4280 # for loops are allowed two ;'s (and may run over two lines).
4281 cleansed_line.find('for') == -1 and
4282 (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
4283 GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
4284 # It's ok to have many commands in a switch case that fits in 1 line
4285 not ((cleansed_line.find('case ') != -1 or
4286 cleansed_line.find('default:') != -1) and
4287 cleansed_line.find('break;') != -1)):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004288 error(filename, linenum, 'whitespace/newline', 0,
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004289 'More than one command on the same line')
4290
4291 # Some more style checks
4292 CheckBraces(filename, clean_lines, linenum, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004293 CheckTrailingSemicolon(filename, clean_lines, linenum, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004294 CheckEmptyBlockBody(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004295 CheckAccess(filename, clean_lines, linenum, nesting_state, error)
4296 CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004297 CheckOperatorSpacing(filename, clean_lines, linenum, error)
4298 CheckParenthesisSpacing(filename, clean_lines, linenum, error)
4299 CheckCommaSpacing(filename, clean_lines, linenum, error)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004300 CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004301 CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004302 CheckCheck(filename, clean_lines, linenum, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004303 CheckAltTokens(filename, clean_lines, linenum, error)
4304 classinfo = nesting_state.InnermostClass()
4305 if classinfo:
4306 CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004307
4308
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004309_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
4310# Matches the first component of a filename delimited by -s and _s. That is:
4311# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
4312# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
4313# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
4314# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
4315_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
4316
4317
4318def _DropCommonSuffixes(filename):
4319 """Drops common suffixes like _test.cc or -inl.h from filename.
4320
4321 For example:
4322 >>> _DropCommonSuffixes('foo/foo-inl.h')
4323 'foo/foo'
4324 >>> _DropCommonSuffixes('foo/bar/foo.cc')
4325 'foo/bar/foo'
4326 >>> _DropCommonSuffixes('foo/foo_internal.h')
4327 'foo/foo'
4328 >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
4329 'foo/foo_unusualinternal'
4330
4331 Args:
4332 filename: The input filename.
4333
4334 Returns:
4335 The filename with the common suffix removed.
4336 """
4337 for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
4338 'inl.h', 'impl.h', 'internal.h'):
4339 if (filename.endswith(suffix) and len(filename) > len(suffix) and
4340 filename[-len(suffix) - 1] in ('-', '_')):
4341 return filename[:-len(suffix) - 1]
4342 return os.path.splitext(filename)[0]
4343
4344
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004345def _ClassifyInclude(fileinfo, include, is_system):
4346 """Figures out what kind of header 'include' is.
4347
4348 Args:
4349 fileinfo: The current file cpplint is running over. A FileInfo instance.
4350 include: The path to a #included file.
4351 is_system: True if the #include used <> rather than "".
4352
4353 Returns:
4354 One of the _XXX_HEADER constants.
4355
4356 For example:
4357 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
4358 _C_SYS_HEADER
4359 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
4360 _CPP_SYS_HEADER
4361 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
4362 _LIKELY_MY_HEADER
4363 >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
4364 ... 'bar/foo_other_ext.h', False)
4365 _POSSIBLE_MY_HEADER
4366 >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
4367 _OTHER_HEADER
4368 """
4369 # This is a list of all standard c++ header files, except
4370 # those already checked for above.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004371 is_cpp_h = include in _CPP_HEADERS
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004372
4373 if is_system:
4374 if is_cpp_h:
4375 return _CPP_SYS_HEADER
4376 else:
4377 return _C_SYS_HEADER
4378
4379 # If the target file and the include we're checking share a
4380 # basename when we drop common extensions, and the include
4381 # lives in . , then it's likely to be owned by the target file.
4382 target_dir, target_base = (
4383 os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
4384 include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
4385 if target_base == include_base and (
4386 include_dir == target_dir or
4387 include_dir == os.path.normpath(target_dir + '/../public')):
4388 return _LIKELY_MY_HEADER
4389
4390 # If the target and include share some initial basename
4391 # component, it's possible the target is implementing the
4392 # include, so it's allowed to be first, but we'll never
4393 # complain if it's not there.
4394 target_first_component = _RE_FIRST_COMPONENT.match(target_base)
4395 include_first_component = _RE_FIRST_COMPONENT.match(include_base)
4396 if (target_first_component and include_first_component and
4397 target_first_component.group(0) ==
4398 include_first_component.group(0)):
4399 return _POSSIBLE_MY_HEADER
4400
4401 return _OTHER_HEADER
4402
4403
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004404
erg@google.com6317a9c2009-06-25 00:28:19 +00004405def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
4406 """Check rules that are applicable to #include lines.
4407
4408 Strings on #include lines are NOT removed from elided line, to make
4409 certain tasks easier. However, to prevent false positives, checks
4410 applicable to #include lines in CheckLanguage must be put here.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004411
4412 Args:
4413 filename: The name of the current file.
4414 clean_lines: A CleansedLines instance containing the file.
4415 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004416 include_state: An _IncludeState instance in which the headers are inserted.
4417 error: The function to call with any errors found.
4418 """
4419 fileinfo = FileInfo(filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00004420 line = clean_lines.lines[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004421
4422 # "include" should use the new style "foo/bar.h" instead of just "bar.h"
avakulenko@google.com59146752014-08-11 20:20:55 +00004423 # Only do this check if the included header follows google naming
4424 # conventions. If not, assume that it's a 3rd party API that
4425 # requires special include conventions.
4426 #
4427 # We also make an exception for Lua headers, which follow google
4428 # naming convention but not the include convention.
4429 match = Match(r'#include\s*"([^/]+\.h)"', line)
4430 if match and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1)):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004431 error(filename, linenum, 'build/include', 4,
4432 'Include the directory when naming .h files')
4433
4434 # we shouldn't include a file more than once. actually, there are a
4435 # handful of instances where doing so is okay, but in general it's
4436 # not.
erg@google.com6317a9c2009-06-25 00:28:19 +00004437 match = _RE_PATTERN_INCLUDE.search(line)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004438 if match:
4439 include = match.group(2)
4440 is_system = (match.group(1) == '<')
avakulenko@google.com59146752014-08-11 20:20:55 +00004441 duplicate_line = include_state.FindHeader(include)
4442 if duplicate_line >= 0:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004443 error(filename, linenum, 'build/include', 4,
4444 '"%s" already included at %s:%s' %
avakulenko@google.com59146752014-08-11 20:20:55 +00004445 (include, filename, duplicate_line))
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004446 elif (include.endswith('.cc') and
4447 os.path.dirname(fileinfo.RepositoryName()) != os.path.dirname(include)):
4448 error(filename, linenum, 'build/include', 4,
4449 'Do not include .cc files from other packages')
avakulenko@google.com59146752014-08-11 20:20:55 +00004450 elif not _THIRD_PARTY_HEADERS_PATTERN.match(include):
4451 include_state.include_list[-1].append((include, linenum))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004452
4453 # We want to ensure that headers appear in the right order:
4454 # 1) for foo.cc, foo.h (preferred location)
4455 # 2) c system files
4456 # 3) cpp system files
4457 # 4) for foo.cc, foo.h (deprecated location)
4458 # 5) other google headers
4459 #
4460 # We classify each include statement as one of those 5 types
4461 # using a number of techniques. The include_state object keeps
4462 # track of the highest type seen, and complains if we see a
4463 # lower type after that.
4464 error_message = include_state.CheckNextIncludeOrder(
4465 _ClassifyInclude(fileinfo, include, is_system))
4466 if error_message:
4467 error(filename, linenum, 'build/include_order', 4,
4468 '%s. Should be: %s.h, c system, c++ system, other.' %
4469 (error_message, fileinfo.BaseName()))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004470 canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
4471 if not include_state.IsInAlphabeticalOrder(
4472 clean_lines, linenum, canonical_include):
erg@google.com26970fa2009-11-17 18:07:32 +00004473 error(filename, linenum, 'build/include_alpha', 4,
4474 'Include "%s" not in alphabetical order' % include)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004475 include_state.SetLastHeader(canonical_include)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004476
erg@google.com6317a9c2009-06-25 00:28:19 +00004477
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004478
4479def _GetTextInside(text, start_pattern):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004480 r"""Retrieves all the text between matching open and close parentheses.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004481
4482 Given a string of lines and a regular expression string, retrieve all the text
4483 following the expression and between opening punctuation symbols like
4484 (, [, or {, and the matching close-punctuation symbol. This properly nested
4485 occurrences of the punctuations, so for the text like
4486 printf(a(), b(c()));
4487 a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'.
4488 start_pattern must match string having an open punctuation symbol at the end.
4489
4490 Args:
4491 text: The lines to extract text. Its comments and strings must be elided.
4492 It can be single line and can span multiple lines.
4493 start_pattern: The regexp string indicating where to start extracting
4494 the text.
4495 Returns:
4496 The extracted text.
4497 None if either the opening string or ending punctuation could not be found.
4498 """
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004499 # TODO(unknown): Audit cpplint.py to see what places could be profitably
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004500 # rewritten to use _GetTextInside (and use inferior regexp matching today).
4501
4502 # Give opening punctuations to get the matching close-punctuations.
4503 matching_punctuation = {'(': ')', '{': '}', '[': ']'}
4504 closing_punctuation = set(matching_punctuation.itervalues())
4505
4506 # Find the position to start extracting text.
4507 match = re.search(start_pattern, text, re.M)
4508 if not match: # start_pattern not found in text.
4509 return None
4510 start_position = match.end(0)
4511
4512 assert start_position > 0, (
4513 'start_pattern must ends with an opening punctuation.')
4514 assert text[start_position - 1] in matching_punctuation, (
4515 'start_pattern must ends with an opening punctuation.')
4516 # Stack of closing punctuations we expect to have in text after position.
4517 punctuation_stack = [matching_punctuation[text[start_position - 1]]]
4518 position = start_position
4519 while punctuation_stack and position < len(text):
4520 if text[position] == punctuation_stack[-1]:
4521 punctuation_stack.pop()
4522 elif text[position] in closing_punctuation:
4523 # A closing punctuation without matching opening punctuations.
4524 return None
4525 elif text[position] in matching_punctuation:
4526 punctuation_stack.append(matching_punctuation[text[position]])
4527 position += 1
4528 if punctuation_stack:
4529 # Opening punctuations left without matching close-punctuations.
4530 return None
4531 # punctuations match.
4532 return text[start_position:position - 1]
4533
4534
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004535# Patterns for matching call-by-reference parameters.
4536#
4537# Supports nested templates up to 2 levels deep using this messy pattern:
4538# < (?: < (?: < [^<>]*
4539# >
4540# | [^<>] )*
4541# >
4542# | [^<>] )*
4543# >
4544_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
4545_RE_PATTERN_TYPE = (
4546 r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
4547 r'(?:\w|'
4548 r'\s*<(?:<(?:<[^<>]*>|[^<>])*>|[^<>])*>|'
4549 r'::)+')
4550# A call-by-reference parameter ends with '& identifier'.
4551_RE_PATTERN_REF_PARAM = re.compile(
4552 r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
4553 r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
4554# A call-by-const-reference parameter either ends with 'const& identifier'
4555# or looks like 'const type& identifier' when 'type' is atomic.
4556_RE_PATTERN_CONST_REF_PARAM = (
4557 r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4558 r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004559# Stream types.
4560_RE_PATTERN_REF_STREAM_PARAM = (
4561 r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')')
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004562
4563
4564def CheckLanguage(filename, clean_lines, linenum, file_extension,
4565 include_state, nesting_state, error):
erg@google.com6317a9c2009-06-25 00:28:19 +00004566 """Checks rules from the 'C++ language rules' section of cppguide.html.
4567
4568 Some of these rules are hard to test (function overloading, using
4569 uint32 inappropriately), but we do the best we can.
4570
4571 Args:
4572 filename: The name of the current file.
4573 clean_lines: A CleansedLines instance containing the file.
4574 linenum: The number of the line to check.
4575 file_extension: The extension (without the dot) of the filename.
4576 include_state: An _IncludeState instance in which the headers are inserted.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004577 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004578 the current stack of nested blocks being parsed.
erg@google.com6317a9c2009-06-25 00:28:19 +00004579 error: The function to call with any errors found.
4580 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004581 # If the line is empty or consists of entirely a comment, no need to
4582 # check it.
4583 line = clean_lines.elided[linenum]
4584 if not line:
4585 return
4586
erg@google.com6317a9c2009-06-25 00:28:19 +00004587 match = _RE_PATTERN_INCLUDE.search(line)
4588 if match:
4589 CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
4590 return
4591
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004592 # Reset include state across preprocessor directives. This is meant
4593 # to silence warnings for conditional includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00004594 match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
4595 if match:
4596 include_state.ResetSection(match.group(1))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004597
4598 # Make Windows paths like Unix.
4599 fullname = os.path.abspath(filename).replace('\\', '/')
skym@chromium.org3990c412016-02-05 20:55:12 +00004600
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004601 # Perform other checks now that we are sure that this is not an include line
4602 CheckCasts(filename, clean_lines, linenum, error)
4603 CheckGlobalStatic(filename, clean_lines, linenum, error)
4604 CheckPrintf(filename, clean_lines, linenum, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004605
4606 if file_extension == 'h':
4607 # TODO(unknown): check that 1-arg constructors are explicit.
4608 # How to tell it's a constructor?
4609 # (handled in CheckForNonStandardConstructs for now)
avakulenko@google.com59146752014-08-11 20:20:55 +00004610 # TODO(unknown): check that classes declare or disable copy/assign
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004611 # (level 1 error)
4612 pass
4613
4614 # Check if people are using the verboten C basic types. The only exception
4615 # we regularly allow is "unsigned short port" for port.
4616 if Search(r'\bshort port\b', line):
4617 if not Search(r'\bunsigned short port\b', line):
4618 error(filename, linenum, 'runtime/int', 4,
4619 'Use "unsigned short" for ports, not "short"')
4620 else:
4621 match = Search(r'\b(short|long(?! +double)|long long)\b', line)
4622 if match:
4623 error(filename, linenum, 'runtime/int', 4,
4624 'Use int16/int64/etc, rather than the C type %s' % match.group(1))
4625
erg@google.com26970fa2009-11-17 18:07:32 +00004626 # Check if some verboten operator overloading is going on
4627 # TODO(unknown): catch out-of-line unary operator&:
4628 # class X {};
4629 # int operator&(const X& x) { return 42; } // unary operator&
4630 # The trick is it's hard to tell apart from binary operator&:
4631 # class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
4632 if Search(r'\boperator\s*&\s*\(\s*\)', line):
4633 error(filename, linenum, 'runtime/operator', 4,
4634 'Unary operator& is dangerous. Do not use it.')
4635
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004636 # Check for suspicious usage of "if" like
4637 # } if (a == b) {
4638 if Search(r'\}\s*if\s*\(', line):
4639 error(filename, linenum, 'readability/braces', 4,
4640 'Did you mean "else if"? If not, start a new line for "if".')
4641
4642 # Check for potential format string bugs like printf(foo).
4643 # We constrain the pattern not to pick things like DocidForPrintf(foo).
4644 # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004645 # TODO(unknown): Catch the following case. Need to change the calling
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004646 # convention of the whole function to process multiple line to handle it.
4647 # printf(
4648 # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
4649 printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
4650 if printf_args:
4651 match = Match(r'([\w.\->()]+)$', printf_args)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00004652 if match and match.group(1) != '__VA_ARGS__':
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004653 function_name = re.search(r'\b((?:string)?printf)\s*\(',
4654 line, re.I).group(1)
4655 error(filename, linenum, 'runtime/printf', 4,
4656 'Potential format string bug. Do %s("%%s", %s) instead.'
4657 % (function_name, match.group(1)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004658
4659 # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
4660 match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
4661 if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
4662 error(filename, linenum, 'runtime/memset', 4,
4663 'Did you mean "memset(%s, 0, %s)"?'
4664 % (match.group(1), match.group(2)))
4665
4666 if Search(r'\busing namespace\b', line):
4667 error(filename, linenum, 'build/namespaces', 5,
4668 'Do not use namespace using-directives. '
4669 'Use using-declarations instead.')
4670
4671 # Detect variable-length arrays.
4672 match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
4673 if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
4674 match.group(3).find(']') == -1):
4675 # Split the size using space and arithmetic operators as delimiters.
4676 # If any of the resulting tokens are not compile time constants then
4677 # report the error.
4678 tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
4679 is_const = True
4680 skip_next = False
4681 for tok in tokens:
4682 if skip_next:
4683 skip_next = False
4684 continue
4685
4686 if Search(r'sizeof\(.+\)', tok): continue
4687 if Search(r'arraysize\(\w+\)', tok): continue
4688
4689 tok = tok.lstrip('(')
4690 tok = tok.rstrip(')')
4691 if not tok: continue
4692 if Match(r'\d+', tok): continue
4693 if Match(r'0[xX][0-9a-fA-F]+', tok): continue
4694 if Match(r'k[A-Z0-9]\w*', tok): continue
4695 if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
4696 if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
4697 # A catch all for tricky sizeof cases, including 'sizeof expression',
4698 # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00004699 # requires skipping the next token because we split on ' ' and '*'.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004700 if tok.startswith('sizeof'):
4701 skip_next = True
4702 continue
4703 is_const = False
4704 break
4705 if not is_const:
4706 error(filename, linenum, 'runtime/arrays', 1,
4707 'Do not use variable-length arrays. Use an appropriately named '
4708 "('k' followed by CamelCase) compile-time constant for the size.")
4709
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004710 # Check for use of unnamed namespaces in header files. Registration
4711 # macros are typically OK, so we allow use of "namespace {" on lines
4712 # that end with backslashes.
4713 if (file_extension == 'h'
4714 and Search(r'\bnamespace\s*{', line)
4715 and line[-1] != '\\'):
4716 error(filename, linenum, 'build/namespaces', 4,
4717 'Do not use unnamed namespaces in header files. See '
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004718 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00004719 ' for more information.')
4720
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004721
4722def CheckGlobalStatic(filename, clean_lines, linenum, error):
4723 """Check for unsafe global or static objects.
4724
4725 Args:
4726 filename: The name of the current file.
4727 clean_lines: A CleansedLines instance containing the file.
4728 linenum: The number of the line to check.
4729 error: The function to call with any errors found.
4730 """
4731 line = clean_lines.elided[linenum]
4732
avakulenko@google.com59146752014-08-11 20:20:55 +00004733 # Match two lines at a time to support multiline declarations
4734 if linenum + 1 < clean_lines.NumLines() and not Search(r'[;({]', line):
4735 line += clean_lines.elided[linenum + 1].strip()
4736
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004737 # Check for people declaring static/global STL strings at the top level.
4738 # This is dangerous because the C++ language does not guarantee that
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004739 # globals with constructors are initialized before the first access, and
4740 # also because globals can be destroyed when some threads are still running.
4741 # TODO(unknown): Generalize this to also find static unique_ptr instances.
4742 # TODO(unknown): File bugs for clang-tidy to find these.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004743 match = Match(
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004744 r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
4745 r'([a-zA-Z0-9_:]+)\b(.*)',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004746 line)
avakulenko@google.com59146752014-08-11 20:20:55 +00004747
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004748 # Remove false positives:
4749 # - String pointers (as opposed to values).
4750 # string *pointer
4751 # const string *pointer
4752 # string const *pointer
4753 # string *const pointer
4754 #
4755 # - Functions and template specializations.
4756 # string Function<Type>(...
4757 # string Class<Type>::Method(...
4758 #
4759 # - Operators. These are matched separately because operator names
4760 # cross non-word boundaries, and trying to match both operators
4761 # and functions at the same time would decrease accuracy of
4762 # matching identifiers.
4763 # string Class::operator*()
4764 if (match and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004765 not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004766 not Search(r'\boperator\W', line) and
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004767 not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
4768 if Search(r'\bconst\b', line):
4769 error(filename, linenum, 'runtime/string', 4,
4770 'For a static/global string constant, use a C style string '
4771 'instead: "%schar%s %s[]".' %
4772 (match.group(1), match.group(2) or '', match.group(3)))
4773 else:
4774 error(filename, linenum, 'runtime/string', 4,
4775 'Static/global string variables are not permitted.')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004776
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00004777 if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
4778 Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004779 error(filename, linenum, 'runtime/init', 4,
4780 'You seem to be initializing a member variable with itself.')
4781
4782
4783def CheckPrintf(filename, clean_lines, linenum, error):
4784 """Check for printf related issues.
4785
4786 Args:
4787 filename: The name of the current file.
4788 clean_lines: A CleansedLines instance containing the file.
4789 linenum: The number of the line to check.
4790 error: The function to call with any errors found.
4791 """
4792 line = clean_lines.elided[linenum]
4793
4794 # When snprintf is used, the second argument shouldn't be a literal.
4795 match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
4796 if match and match.group(2) != '0':
4797 # If 2nd arg is zero, snprintf is used to calculate size.
4798 error(filename, linenum, 'runtime/printf', 3,
4799 'If you can, use sizeof(%s) instead of %s as the 2nd arg '
4800 'to snprintf.' % (match.group(1), match.group(2)))
4801
4802 # Check if some verboten C functions are being used.
avakulenko@google.com59146752014-08-11 20:20:55 +00004803 if Search(r'\bsprintf\s*\(', line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004804 error(filename, linenum, 'runtime/printf', 5,
4805 'Never use sprintf. Use snprintf instead.')
avakulenko@google.com59146752014-08-11 20:20:55 +00004806 match = Search(r'\b(strcpy|strcat)\s*\(', line)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004807 if match:
4808 error(filename, linenum, 'runtime/printf', 4,
4809 'Almost always, snprintf is better than %s' % match.group(1))
4810
4811
4812def IsDerivedFunction(clean_lines, linenum):
4813 """Check if current line contains an inherited function.
4814
4815 Args:
4816 clean_lines: A CleansedLines instance containing the file.
4817 linenum: The number of the line to check.
4818 Returns:
4819 True if current line contains a function with "override"
4820 virt-specifier.
4821 """
avakulenko@google.com59146752014-08-11 20:20:55 +00004822 # Scan back a few lines for start of current function
4823 for i in xrange(linenum, max(-1, linenum - 10), -1):
4824 match = Match(r'^([^()]*\w+)\(', clean_lines.elided[i])
4825 if match:
4826 # Look for "override" after the matching closing parenthesis
4827 line, _, closing_paren = CloseExpression(
4828 clean_lines, i, len(match.group(1)))
4829 return (closing_paren >= 0 and
4830 Search(r'\boverride\b', line[closing_paren:]))
4831 return False
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004832
4833
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004834def IsOutOfLineMethodDefinition(clean_lines, linenum):
4835 """Check if current line contains an out-of-line method definition.
4836
4837 Args:
4838 clean_lines: A CleansedLines instance containing the file.
4839 linenum: The number of the line to check.
4840 Returns:
4841 True if current line contains an out-of-line method definition.
4842 """
4843 # Scan back a few lines for start of current function
4844 for i in xrange(linenum, max(-1, linenum - 10), -1):
4845 if Match(r'^([^()]*\w+)\(', clean_lines.elided[i]):
4846 return Match(r'^[^()]*\w+::\w+\(', clean_lines.elided[i]) is not None
4847 return False
4848
4849
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004850def IsInitializerList(clean_lines, linenum):
4851 """Check if current line is inside constructor initializer list.
4852
4853 Args:
4854 clean_lines: A CleansedLines instance containing the file.
4855 linenum: The number of the line to check.
4856 Returns:
4857 True if current line appears to be inside constructor initializer
4858 list, False otherwise.
4859 """
4860 for i in xrange(linenum, 1, -1):
4861 line = clean_lines.elided[i]
4862 if i == linenum:
4863 remove_function_body = Match(r'^(.*)\{\s*$', line)
4864 if remove_function_body:
4865 line = remove_function_body.group(1)
4866
4867 if Search(r'\s:\s*\w+[({]', line):
4868 # A lone colon tend to indicate the start of a constructor
4869 # initializer list. It could also be a ternary operator, which
4870 # also tend to appear in constructor initializer lists as
4871 # opposed to parameter lists.
4872 return True
4873 if Search(r'\}\s*,\s*$', line):
4874 # A closing brace followed by a comma is probably the end of a
4875 # brace-initialized member in constructor initializer list.
4876 return True
4877 if Search(r'[{};]\s*$', line):
4878 # Found one of the following:
4879 # - A closing brace or semicolon, probably the end of the previous
4880 # function.
4881 # - An opening brace, probably the start of current class or namespace.
4882 #
4883 # Current line is probably not inside an initializer list since
4884 # we saw one of those things without seeing the starting colon.
4885 return False
4886
4887 # Got to the beginning of the file without seeing the start of
4888 # constructor initializer list.
4889 return False
4890
4891
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004892def CheckForNonConstReference(filename, clean_lines, linenum,
4893 nesting_state, error):
4894 """Check for non-const references.
4895
4896 Separate from CheckLanguage since it scans backwards from current
4897 line, instead of scanning forward.
4898
4899 Args:
4900 filename: The name of the current file.
4901 clean_lines: A CleansedLines instance containing the file.
4902 linenum: The number of the line to check.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004903 nesting_state: A NestingState instance which maintains information about
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004904 the current stack of nested blocks being parsed.
4905 error: The function to call with any errors found.
4906 """
4907 # Do nothing if there is no '&' on current line.
4908 line = clean_lines.elided[linenum]
4909 if '&' not in line:
4910 return
4911
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004912 # If a function is inherited, current function doesn't have much of
4913 # a choice, so any non-const references should not be blamed on
4914 # derived function.
4915 if IsDerivedFunction(clean_lines, linenum):
4916 return
4917
avakulenko@google.com255f2be2014-12-05 22:19:55 +00004918 # Don't warn on out-of-line method definitions, as we would warn on the
4919 # in-line declaration, if it isn't marked with 'override'.
4920 if IsOutOfLineMethodDefinition(clean_lines, linenum):
4921 return
4922
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004923 # Long type names may be broken across multiple lines, usually in one
4924 # of these forms:
4925 # LongType
4926 # ::LongTypeContinued &identifier
4927 # LongType::
4928 # LongTypeContinued &identifier
4929 # LongType<
4930 # ...>::LongTypeContinued &identifier
4931 #
4932 # If we detected a type split across two lines, join the previous
4933 # line to current line so that we can match const references
4934 # accordingly.
4935 #
4936 # Note that this only scans back one line, since scanning back
4937 # arbitrary number of lines would be expensive. If you have a type
4938 # that spans more than 2 lines, please use a typedef.
4939 if linenum > 1:
4940 previous = None
4941 if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
4942 # previous_line\n + ::current_line
4943 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
4944 clean_lines.elided[linenum - 1])
4945 elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
4946 # previous_line::\n + current_line
4947 previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
4948 clean_lines.elided[linenum - 1])
4949 if previous:
4950 line = previous.group(1) + line.lstrip()
4951 else:
4952 # Check for templated parameter that is split across multiple lines
4953 endpos = line.rfind('>')
4954 if endpos > -1:
4955 (_, startline, startpos) = ReverseCloseExpression(
4956 clean_lines, linenum, endpos)
4957 if startpos > -1 and startline < linenum:
4958 # Found the matching < on an earlier line, collect all
4959 # pieces up to current line.
4960 line = ''
4961 for i in xrange(startline, linenum + 1):
4962 line += clean_lines.elided[i].strip()
4963
4964 # Check for non-const references in function parameters. A single '&' may
4965 # found in the following places:
4966 # inside expression: binary & for bitwise AND
4967 # inside expression: unary & for taking the address of something
4968 # inside declarators: reference parameter
4969 # We will exclude the first two cases by checking that we are not inside a
4970 # function body, including one that was just introduced by a trailing '{'.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00004971 # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004972 if (nesting_state.previous_stack_top and
4973 not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
4974 isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
4975 # Not at toplevel, not within a class, and not within a namespace
4976 return
4977
avakulenko@google.com59146752014-08-11 20:20:55 +00004978 # Avoid initializer lists. We only need to scan back from the
4979 # current line for something that starts with ':'.
4980 #
4981 # We don't need to check the current line, since the '&' would
4982 # appear inside the second set of parentheses on the current line as
4983 # opposed to the first set.
4984 if linenum > 0:
4985 for i in xrange(linenum - 1, max(0, linenum - 10), -1):
4986 previous_line = clean_lines.elided[i]
4987 if not Search(r'[),]\s*$', previous_line):
4988 break
4989 if Match(r'^\s*:\s+\S', previous_line):
4990 return
4991
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00004992 # Avoid preprocessors
4993 if Search(r'\\\s*$', line):
4994 return
4995
4996 # Avoid constructor initializer lists
4997 if IsInitializerList(clean_lines, linenum):
4998 return
4999
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005000 # We allow non-const references in a few standard places, like functions
5001 # called "swap()" or iostream operators like "<<" or ">>". Do not check
5002 # those function parameters.
5003 #
5004 # We also accept & in static_assert, which looks like a function but
5005 # it's actually a declaration expression.
5006 whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
5007 r'operator\s*[<>][<>]|'
5008 r'static_assert|COMPILE_ASSERT'
5009 r')\s*\(')
5010 if Search(whitelisted_functions, line):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005011 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005012 elif not Search(r'\S+\([^)]*$', line):
5013 # Don't see a whitelisted function on this line. Actually we
5014 # didn't see any function name on this line, so this is likely a
5015 # multi-line parameter list. Try a bit harder to catch this case.
5016 for i in xrange(2):
5017 if (linenum > i and
5018 Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005019 return
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005020
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005021 decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
5022 for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005023 if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
5024 not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005025 error(filename, linenum, 'runtime/references', 2,
5026 'Is this a non-const reference? '
5027 'If so, make const or use a pointer: ' +
5028 ReplaceAll(' *<', '<', parameter))
5029
5030
5031def CheckCasts(filename, clean_lines, linenum, error):
5032 """Various cast related checks.
5033
5034 Args:
5035 filename: The name of the current file.
5036 clean_lines: A CleansedLines instance containing the file.
5037 linenum: The number of the line to check.
5038 error: The function to call with any errors found.
5039 """
5040 line = clean_lines.elided[linenum]
5041
5042 # Check to see if they're using an conversion function cast.
5043 # I just try to capture the most common basic types, though there are more.
5044 # Parameterless conversion functions, such as bool(), are allowed as they are
5045 # probably a member operator declaration or default constructor.
5046 match = Search(
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005047 r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005048 r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
5049 r'(\([^)].*)', line)
5050 expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
5051 if match and not expecting_function:
5052 matched_type = match.group(2)
5053
5054 # matched_new_or_template is used to silence two false positives:
5055 # - New operators
5056 # - Template arguments with function types
5057 #
5058 # For template arguments, we match on types immediately following
5059 # an opening bracket without any spaces. This is a fast way to
5060 # silence the common case where the function type is the first
5061 # template argument. False negative with less-than comparison is
5062 # avoided because those operators are usually followed by a space.
5063 #
5064 # function<double(double)> // bracket + no space = false positive
5065 # value < double(42) // bracket + space = true positive
5066 matched_new_or_template = match.group(1)
5067
avakulenko@google.com59146752014-08-11 20:20:55 +00005068 # Avoid arrays by looking for brackets that come after the closing
5069 # parenthesis.
5070 if Match(r'\([^()]+\)\s*\[', match.group(3)):
5071 return
5072
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005073 # Other things to ignore:
5074 # - Function pointers
5075 # - Casts to pointer types
5076 # - Placement new
5077 # - Alias declarations
5078 matched_funcptr = match.group(3)
5079 if (matched_new_or_template is None and
5080 not (matched_funcptr and
5081 (Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
5082 matched_funcptr) or
5083 matched_funcptr.startswith('(*)'))) and
5084 not Match(r'\s*using\s+\S+\s*=\s*' + matched_type, line) and
5085 not Search(r'new\(\S+\)\s*' + matched_type, line)):
5086 error(filename, linenum, 'readability/casting', 4,
5087 'Using deprecated casting style. '
5088 'Use static_cast<%s>(...) instead' %
5089 matched_type)
5090
5091 if not expecting_function:
avakulenko@google.com59146752014-08-11 20:20:55 +00005092 CheckCStyleCast(filename, clean_lines, linenum, 'static_cast',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005093 r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
5094
5095 # This doesn't catch all cases. Consider (const char * const)"hello".
5096 #
5097 # (char *) "foo" should always be a const_cast (reinterpret_cast won't
5098 # compile).
avakulenko@google.com59146752014-08-11 20:20:55 +00005099 if CheckCStyleCast(filename, clean_lines, linenum, 'const_cast',
5100 r'\((char\s?\*+\s?)\)\s*"', error):
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005101 pass
5102 else:
5103 # Check pointer casts for other than string constants
avakulenko@google.com59146752014-08-11 20:20:55 +00005104 CheckCStyleCast(filename, clean_lines, linenum, 'reinterpret_cast',
5105 r'\((\w+\s?\*+\s?)\)', error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005106
5107 # In addition, we look for people taking the address of a cast. This
5108 # is dangerous -- casts can assign to temporaries, so the pointer doesn't
5109 # point where you think.
avakulenko@google.com59146752014-08-11 20:20:55 +00005110 #
5111 # Some non-identifier character is required before the '&' for the
5112 # expression to be recognized as a cast. These are casts:
5113 # expression = &static_cast<int*>(temporary());
5114 # function(&(int*)(temporary()));
5115 #
5116 # This is not a cast:
5117 # reference_type&(int* function_param);
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005118 match = Search(
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005119 r'(?:[^\w]&\(([^)*][^)]*)\)[\w(])|'
avakulenko@google.com59146752014-08-11 20:20:55 +00005120 r'(?:[^\w]&(static|dynamic|down|reinterpret)_cast\b)', line)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005121 if match:
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005122 # Try a better error message when the & is bound to something
5123 # dereferenced by the casted pointer, as opposed to the casted
5124 # pointer itself.
5125 parenthesis_error = False
5126 match = Match(r'^(.*&(?:static|dynamic|down|reinterpret)_cast\b)<', line)
5127 if match:
5128 _, y1, x1 = CloseExpression(clean_lines, linenum, len(match.group(1)))
5129 if x1 >= 0 and clean_lines.elided[y1][x1] == '(':
5130 _, y2, x2 = CloseExpression(clean_lines, y1, x1)
5131 if x2 >= 0:
5132 extended_line = clean_lines.elided[y2][x2:]
5133 if y2 < clean_lines.NumLines() - 1:
5134 extended_line += clean_lines.elided[y2 + 1]
5135 if Match(r'\s*(?:->|\[)', extended_line):
5136 parenthesis_error = True
5137
5138 if parenthesis_error:
5139 error(filename, linenum, 'readability/casting', 4,
5140 ('Are you taking an address of something dereferenced '
5141 'from a cast? Wrapping the dereferenced expression in '
5142 'parentheses will make the binding more obvious'))
5143 else:
5144 error(filename, linenum, 'runtime/casting', 4,
5145 ('Are you taking an address of a cast? '
5146 'This is dangerous: could be a temp var. '
5147 'Take the address before doing the cast, rather than after'))
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005148
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005149
avakulenko@google.com59146752014-08-11 20:20:55 +00005150def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005151 """Checks for a C-style cast by looking for the pattern.
5152
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005153 Args:
5154 filename: The name of the current file.
avakulenko@google.com59146752014-08-11 20:20:55 +00005155 clean_lines: A CleansedLines instance containing the file.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005156 linenum: The number of the line to check.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005157 cast_type: The string for the C++ cast to recommend. This is either
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005158 reinterpret_cast, static_cast, or const_cast, depending.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005159 pattern: The regular expression used to find C-style casts.
5160 error: The function to call with any errors found.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005161
5162 Returns:
5163 True if an error was emitted.
5164 False otherwise.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005165 """
avakulenko@google.com59146752014-08-11 20:20:55 +00005166 line = clean_lines.elided[linenum]
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005167 match = Search(pattern, line)
5168 if not match:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005169 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005170
avakulenko@google.com59146752014-08-11 20:20:55 +00005171 # Exclude lines with keywords that tend to look like casts
5172 context = line[0:match.start(1) - 1]
5173 if Match(r'.*\b(?:sizeof|alignof|alignas|[_A-Z][_A-Z0-9]*)\s*$', context):
5174 return False
5175
5176 # Try expanding current context to see if we one level of
5177 # parentheses inside a macro.
5178 if linenum > 0:
5179 for i in xrange(linenum - 1, max(0, linenum - 5), -1):
5180 context = clean_lines.elided[i] + context
5181 if Match(r'.*\b[_A-Z][_A-Z0-9]*\s*\((?:\([^()]*\)|[^()])*$', context):
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005182 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005183
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005184 # operator++(int) and operator--(int)
avakulenko@google.com59146752014-08-11 20:20:55 +00005185 if context.endswith(' operator++') or context.endswith(' operator--'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005186 return False
5187
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005188 # A single unnamed argument for a function tends to look like old style cast.
5189 # If we see those, don't issue warnings for deprecated casts.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005190 remainder = line[match.end(0):]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005191 if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005192 remainder):
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005193 return False
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005194
5195 # At this point, all that should be left is actual casts.
5196 error(filename, linenum, 'readability/casting', 4,
5197 'Using C-style cast. Use %s<%s>(...) instead' %
5198 (cast_type, match.group(1)))
5199
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005200 return True
5201
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005202
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005203def ExpectingFunctionArgs(clean_lines, linenum):
5204 """Checks whether where function type arguments are expected.
5205
5206 Args:
5207 clean_lines: A CleansedLines instance containing the file.
5208 linenum: The number of the line to check.
5209
5210 Returns:
5211 True if the line at 'linenum' is inside something that expects arguments
5212 of function types.
5213 """
5214 line = clean_lines.elided[linenum]
5215 return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
5216 (linenum >= 2 and
5217 (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
5218 clean_lines.elided[linenum - 1]) or
5219 Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
5220 clean_lines.elided[linenum - 2]) or
5221 Search(r'\bstd::m?function\s*\<\s*$',
5222 clean_lines.elided[linenum - 1]))))
5223
5224
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005225_HEADERS_CONTAINING_TEMPLATES = (
5226 ('<deque>', ('deque',)),
5227 ('<functional>', ('unary_function', 'binary_function',
5228 'plus', 'minus', 'multiplies', 'divides', 'modulus',
5229 'negate',
5230 'equal_to', 'not_equal_to', 'greater', 'less',
5231 'greater_equal', 'less_equal',
5232 'logical_and', 'logical_or', 'logical_not',
5233 'unary_negate', 'not1', 'binary_negate', 'not2',
5234 'bind1st', 'bind2nd',
5235 'pointer_to_unary_function',
5236 'pointer_to_binary_function',
5237 'ptr_fun',
5238 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
5239 'mem_fun_ref_t',
5240 'const_mem_fun_t', 'const_mem_fun1_t',
5241 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
5242 'mem_fun_ref',
5243 )),
5244 ('<limits>', ('numeric_limits',)),
5245 ('<list>', ('list',)),
5246 ('<map>', ('map', 'multimap',)),
5247 ('<memory>', ('allocator',)),
5248 ('<queue>', ('queue', 'priority_queue',)),
5249 ('<set>', ('set', 'multiset',)),
5250 ('<stack>', ('stack',)),
5251 ('<string>', ('char_traits', 'basic_string',)),
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005252 ('<tuple>', ('tuple',)),
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005253 ('<utility>', ('pair',)),
5254 ('<vector>', ('vector',)),
5255
5256 # gcc extensions.
5257 # Note: std::hash is their hash, ::hash is our hash
5258 ('<hash_map>', ('hash_map', 'hash_multimap',)),
5259 ('<hash_set>', ('hash_set', 'hash_multiset',)),
5260 ('<slist>', ('slist',)),
5261 )
5262
skym@chromium.org3990c412016-02-05 20:55:12 +00005263_HEADERS_MAYBE_TEMPLATES = (
5264 ('<algorithm>', ('copy', 'max', 'min', 'min_element', 'sort',
5265 'transform',
5266 )),
5267 ('<utility>', ('swap',)),
5268 )
5269
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005270_RE_PATTERN_STRING = re.compile(r'\bstring\b')
5271
skym@chromium.org3990c412016-02-05 20:55:12 +00005272_re_pattern_headers_maybe_templates = []
5273for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
5274 for _template in _templates:
5275 # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
5276 # type::max().
5277 _re_pattern_headers_maybe_templates.append(
5278 (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
5279 _template,
5280 _header))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005281
skym@chromium.org3990c412016-02-05 20:55:12 +00005282# Other scripts may reach in and modify this pattern.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005283_re_pattern_templates = []
5284for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
5285 for _template in _templates:
5286 _re_pattern_templates.append(
5287 (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
5288 _template + '<>',
5289 _header))
5290
5291
erg@google.com6317a9c2009-06-25 00:28:19 +00005292def FilesBelongToSameModule(filename_cc, filename_h):
5293 """Check if these two filenames belong to the same module.
5294
5295 The concept of a 'module' here is a as follows:
5296 foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
5297 same 'module' if they are in the same directory.
5298 some/path/public/xyzzy and some/path/internal/xyzzy are also considered
5299 to belong to the same module here.
5300
5301 If the filename_cc contains a longer path than the filename_h, for example,
5302 '/absolute/path/to/base/sysinfo.cc', and this file would include
5303 'base/sysinfo.h', this function also produces the prefix needed to open the
5304 header. This is used by the caller of this function to more robustly open the
5305 header file. We don't have access to the real include paths in this context,
5306 so we need this guesswork here.
5307
5308 Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
5309 according to this implementation. Because of this, this function gives
5310 some false positives. This should be sufficiently rare in practice.
5311
5312 Args:
5313 filename_cc: is the path for the .cc file
5314 filename_h: is the path for the header path
5315
5316 Returns:
5317 Tuple with a bool and a string:
5318 bool: True if filename_cc and filename_h belong to the same module.
5319 string: the additional prefix needed to open the header file.
5320 """
5321
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005322 fileinfo = FileInfo(filename_cc)
5323 if not fileinfo.IsSource():
erg@google.com6317a9c2009-06-25 00:28:19 +00005324 return (False, '')
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005325 filename_cc = filename_cc[:-len(fileinfo.Extension())]
5326 matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName())
5327 if matched_test_suffix:
5328 filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
erg@google.com6317a9c2009-06-25 00:28:19 +00005329 filename_cc = filename_cc.replace('/public/', '/')
5330 filename_cc = filename_cc.replace('/internal/', '/')
5331
5332 if not filename_h.endswith('.h'):
5333 return (False, '')
5334 filename_h = filename_h[:-len('.h')]
5335 if filename_h.endswith('-inl'):
5336 filename_h = filename_h[:-len('-inl')]
5337 filename_h = filename_h.replace('/public/', '/')
5338 filename_h = filename_h.replace('/internal/', '/')
5339
5340 files_belong_to_same_module = filename_cc.endswith(filename_h)
5341 common_path = ''
5342 if files_belong_to_same_module:
5343 common_path = filename_cc[:-len(filename_h)]
5344 return files_belong_to_same_module, common_path
5345
5346
avakulenko@google.com59146752014-08-11 20:20:55 +00005347def UpdateIncludeState(filename, include_dict, io=codecs):
5348 """Fill up the include_dict with new includes found from the file.
erg@google.com6317a9c2009-06-25 00:28:19 +00005349
5350 Args:
5351 filename: the name of the header to read.
avakulenko@google.com59146752014-08-11 20:20:55 +00005352 include_dict: a dictionary in which the headers are inserted.
erg@google.com6317a9c2009-06-25 00:28:19 +00005353 io: The io factory to use to read the file. Provided for testability.
5354
5355 Returns:
avakulenko@google.com59146752014-08-11 20:20:55 +00005356 True if a header was successfully added. False otherwise.
erg@google.com6317a9c2009-06-25 00:28:19 +00005357 """
5358 headerfile = None
5359 try:
5360 headerfile = io.open(filename, 'r', 'utf8', 'replace')
5361 except IOError:
5362 return False
5363 linenum = 0
5364 for line in headerfile:
5365 linenum += 1
5366 clean_line = CleanseComments(line)
5367 match = _RE_PATTERN_INCLUDE.search(clean_line)
5368 if match:
5369 include = match.group(2)
avakulenko@google.com59146752014-08-11 20:20:55 +00005370 include_dict.setdefault(include, linenum)
erg@google.com6317a9c2009-06-25 00:28:19 +00005371 return True
5372
5373
5374def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
5375 io=codecs):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005376 """Reports for missing stl includes.
5377
5378 This function will output warnings to make sure you are including the headers
5379 necessary for the stl containers and functions that you use. We only give one
5380 reason to include a header. For example, if you use both equal_to<> and
5381 less<> in a .h file, only one (the latter in the file) of these will be
5382 reported as a reason to include the <functional>.
5383
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005384 Args:
5385 filename: The name of the current file.
5386 clean_lines: A CleansedLines instance containing the file.
5387 include_state: An _IncludeState instance.
5388 error: The function to call with any errors found.
erg@google.com6317a9c2009-06-25 00:28:19 +00005389 io: The IO factory to use to read the header file. Provided for unittest
5390 injection.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005391 """
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005392 required = {} # A map of header name to linenumber and the template entity.
5393 # Example of required: { '<functional>': (1219, 'less<>') }
5394
5395 for linenum in xrange(clean_lines.NumLines()):
5396 line = clean_lines.elided[linenum]
5397 if not line or line[0] == '#':
5398 continue
5399
5400 # String is special -- it is a non-templatized type in STL.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005401 matched = _RE_PATTERN_STRING.search(line)
5402 if matched:
erg@google.com35589e62010-11-17 18:58:16 +00005403 # Don't warn about strings in non-STL namespaces:
5404 # (We check only the first match per line; good enough.)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005405 prefix = line[:matched.start()]
erg@google.com35589e62010-11-17 18:58:16 +00005406 if prefix.endswith('std::') or not prefix.endswith('::'):
5407 required['<string>'] = (linenum, 'string')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005408
skym@chromium.org3990c412016-02-05 20:55:12 +00005409 for pattern, template, header in _re_pattern_headers_maybe_templates:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005410 if pattern.search(line):
5411 required[header] = (linenum, template)
5412
5413 # The following function is just a speed up, no semantics are changed.
5414 if not '<' in line: # Reduces the cpu time usage by skipping lines.
5415 continue
5416
5417 for pattern, template, header in _re_pattern_templates:
5418 if pattern.search(line):
5419 required[header] = (linenum, template)
5420
erg@google.com6317a9c2009-06-25 00:28:19 +00005421 # The policy is that if you #include something in foo.h you don't need to
5422 # include it again in foo.cc. Here, we will look at possible includes.
avakulenko@google.com59146752014-08-11 20:20:55 +00005423 # Let's flatten the include_state include_list and copy it into a dictionary.
5424 include_dict = dict([item for sublist in include_state.include_list
5425 for item in sublist])
erg@google.com6317a9c2009-06-25 00:28:19 +00005426
avakulenko@google.com59146752014-08-11 20:20:55 +00005427 # Did we find the header for this file (if any) and successfully load it?
erg@google.com6317a9c2009-06-25 00:28:19 +00005428 header_found = False
5429
5430 # Use the absolute path so that matching works properly.
erg@chromium.org8f927562012-01-30 19:51:28 +00005431 abs_filename = FileInfo(filename).FullName()
erg@google.com6317a9c2009-06-25 00:28:19 +00005432
5433 # For Emacs's flymake.
5434 # If cpplint is invoked from Emacs's flymake, a temporary file is generated
5435 # by flymake and that file name might end with '_flymake.cc'. In that case,
5436 # restore original file name here so that the corresponding header file can be
5437 # found.
5438 # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
5439 # instead of 'foo_flymake.h'
erg@google.com35589e62010-11-17 18:58:16 +00005440 abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
erg@google.com6317a9c2009-06-25 00:28:19 +00005441
avakulenko@google.com59146752014-08-11 20:20:55 +00005442 # include_dict is modified during iteration, so we iterate over a copy of
erg@google.com6317a9c2009-06-25 00:28:19 +00005443 # the keys.
avakulenko@google.com59146752014-08-11 20:20:55 +00005444 header_keys = include_dict.keys()
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005445 for header in header_keys:
erg@google.com6317a9c2009-06-25 00:28:19 +00005446 (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
5447 fullpath = common_path + header
avakulenko@google.com59146752014-08-11 20:20:55 +00005448 if same_module and UpdateIncludeState(fullpath, include_dict, io):
erg@google.com6317a9c2009-06-25 00:28:19 +00005449 header_found = True
5450
5451 # If we can't find the header file for a .cc, assume it's because we don't
5452 # know where to look. In that case we'll give up as we're not sure they
5453 # didn't include it in the .h file.
5454 # TODO(unknown): Do a better job of finding .h files so we are confident that
5455 # not having the .h file means there isn't one.
5456 if filename.endswith('.cc') and not header_found:
5457 return
5458
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005459 # All the lines have been processed, report the errors found.
5460 for required_header_unstripped in required:
5461 template = required[required_header_unstripped][1]
avakulenko@google.com59146752014-08-11 20:20:55 +00005462 if required_header_unstripped.strip('<>"') not in include_dict:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005463 error(filename, required[required_header_unstripped][0],
5464 'build/include_what_you_use', 4,
5465 'Add #include ' + required_header_unstripped + ' for ' + template)
5466
5467
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005468_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<')
5469
5470
5471def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
5472 """Check that make_pair's template arguments are deduced.
5473
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005474 G++ 4.6 in C++11 mode fails badly if make_pair's template arguments are
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005475 specified explicitly, and such use isn't intended in any case.
5476
5477 Args:
5478 filename: The name of the current file.
5479 clean_lines: A CleansedLines instance containing the file.
5480 linenum: The number of the line to check.
5481 error: The function to call with any errors found.
5482 """
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005483 line = clean_lines.elided[linenum]
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005484 match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line)
5485 if match:
5486 error(filename, linenum, 'build/explicit_make_pair',
5487 4, # 4 = high confidence
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005488 'For C++11-compatibility, omit template arguments from make_pair'
5489 ' OR use pair directly OR if appropriate, construct a pair directly')
avakulenko@google.com59146752014-08-11 20:20:55 +00005490
5491
avakulenko@google.com59146752014-08-11 20:20:55 +00005492def CheckRedundantVirtual(filename, clean_lines, linenum, error):
5493 """Check if line contains a redundant "virtual" function-specifier.
5494
5495 Args:
5496 filename: The name of the current file.
5497 clean_lines: A CleansedLines instance containing the file.
5498 linenum: The number of the line to check.
5499 error: The function to call with any errors found.
5500 """
5501 # Look for "virtual" on current line.
5502 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005503 virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line)
avakulenko@google.com59146752014-08-11 20:20:55 +00005504 if not virtual: return
5505
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005506 # Ignore "virtual" keywords that are near access-specifiers. These
5507 # are only used in class base-specifier and do not apply to member
5508 # functions.
5509 if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or
5510 Match(r'^\s+(public|protected|private)\b', virtual.group(3))):
5511 return
5512
5513 # Ignore the "virtual" keyword from virtual base classes. Usually
5514 # there is a column on the same line in these cases (virtual base
5515 # classes are rare in google3 because multiple inheritance is rare).
5516 if Match(r'^.*[^:]:[^:].*$', line): return
5517
avakulenko@google.com59146752014-08-11 20:20:55 +00005518 # Look for the next opening parenthesis. This is the start of the
5519 # parameter list (possibly on the next line shortly after virtual).
5520 # TODO(unknown): doesn't work if there are virtual functions with
5521 # decltype() or other things that use parentheses, but csearch suggests
5522 # that this is rare.
5523 end_col = -1
5524 end_line = -1
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005525 start_col = len(virtual.group(2))
avakulenko@google.com59146752014-08-11 20:20:55 +00005526 for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())):
5527 line = clean_lines.elided[start_line][start_col:]
5528 parameter_list = Match(r'^([^(]*)\(', line)
5529 if parameter_list:
5530 # Match parentheses to find the end of the parameter list
5531 (_, end_line, end_col) = CloseExpression(
5532 clean_lines, start_line, start_col + len(parameter_list.group(1)))
5533 break
5534 start_col = 0
5535
5536 if end_col < 0:
5537 return # Couldn't find end of parameter list, give up
5538
5539 # Look for "override" or "final" after the parameter list
5540 # (possibly on the next few lines).
5541 for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())):
5542 line = clean_lines.elided[i][end_col:]
5543 match = Search(r'\b(override|final)\b', line)
5544 if match:
5545 error(filename, linenum, 'readability/inheritance', 4,
5546 ('"virtual" is redundant since function is '
5547 'already declared as "%s"' % match.group(1)))
5548
5549 # Set end_col to check whole lines after we are done with the
5550 # first line.
5551 end_col = 0
5552 if Search(r'[^\w]\s*$', line):
5553 break
5554
5555
5556def CheckRedundantOverrideOrFinal(filename, clean_lines, linenum, error):
5557 """Check if line contains a redundant "override" or "final" virt-specifier.
5558
5559 Args:
5560 filename: The name of the current file.
5561 clean_lines: A CleansedLines instance containing the file.
5562 linenum: The number of the line to check.
5563 error: The function to call with any errors found.
5564 """
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005565 # Look for closing parenthesis nearby. We need one to confirm where
5566 # the declarator ends and where the virt-specifier starts to avoid
5567 # false positives.
avakulenko@google.com59146752014-08-11 20:20:55 +00005568 line = clean_lines.elided[linenum]
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005569 declarator_end = line.rfind(')')
5570 if declarator_end >= 0:
5571 fragment = line[declarator_end:]
5572 else:
5573 if linenum > 1 and clean_lines.elided[linenum - 1].rfind(')') >= 0:
5574 fragment = line
5575 else:
5576 return
5577
5578 # Check that at most one of "override" or "final" is present, not both
5579 if Search(r'\boverride\b', fragment) and Search(r'\bfinal\b', fragment):
avakulenko@google.com59146752014-08-11 20:20:55 +00005580 error(filename, linenum, 'readability/inheritance', 4,
5581 ('"override" is redundant since function is '
5582 'already declared as "final"'))
5583
5584
5585
5586
5587# Returns true if we are at a new block, and it is directly
5588# inside of a namespace.
5589def IsBlockInNameSpace(nesting_state, is_forward_declaration):
5590 """Checks that the new block is directly in a namespace.
5591
5592 Args:
5593 nesting_state: The _NestingState object that contains info about our state.
5594 is_forward_declaration: If the class is a forward declared class.
5595 Returns:
5596 Whether or not the new block is directly in a namespace.
5597 """
5598 if is_forward_declaration:
5599 if len(nesting_state.stack) >= 1 and (
5600 isinstance(nesting_state.stack[-1], _NamespaceInfo)):
5601 return True
5602 else:
5603 return False
5604
5605 return (len(nesting_state.stack) > 1 and
5606 nesting_state.stack[-1].check_namespace_indentation and
5607 isinstance(nesting_state.stack[-2], _NamespaceInfo))
5608
5609
5610def ShouldCheckNamespaceIndentation(nesting_state, is_namespace_indent_item,
5611 raw_lines_no_comments, linenum):
5612 """This method determines if we should apply our namespace indentation check.
5613
5614 Args:
5615 nesting_state: The current nesting state.
5616 is_namespace_indent_item: If we just put a new class on the stack, True.
5617 If the top of the stack is not a class, or we did not recently
5618 add the class, False.
5619 raw_lines_no_comments: The lines without the comments.
5620 linenum: The current line number we are processing.
5621
5622 Returns:
5623 True if we should apply our namespace indentation check. Currently, it
5624 only works for classes and namespaces inside of a namespace.
5625 """
5626
5627 is_forward_declaration = IsForwardClassDeclaration(raw_lines_no_comments,
5628 linenum)
5629
5630 if not (is_namespace_indent_item or is_forward_declaration):
5631 return False
5632
5633 # If we are in a macro, we do not want to check the namespace indentation.
5634 if IsMacroDefinition(raw_lines_no_comments, linenum):
5635 return False
5636
5637 return IsBlockInNameSpace(nesting_state, is_forward_declaration)
5638
5639
5640# Call this method if the line is directly inside of a namespace.
5641# If the line above is blank (excluding comments) or the start of
5642# an inner namespace, it cannot be indented.
5643def CheckItemIndentationInNamespace(filename, raw_lines_no_comments, linenum,
5644 error):
5645 line = raw_lines_no_comments[linenum]
5646 if Match(r'^\s+', line):
5647 error(filename, linenum, 'runtime/indentation_namespace', 4,
5648 'Do not indent within a namespace')
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005649
5650
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005651def ProcessLine(filename, file_extension, clean_lines, line,
5652 include_state, function_state, nesting_state, error,
5653 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005654 """Processes a single line in the file.
5655
5656 Args:
5657 filename: Filename of the file that is being processed.
5658 file_extension: The extension (dot not included) of the file.
5659 clean_lines: An array of strings, each representing a line of the file,
5660 with comments stripped.
5661 line: Number of line being processed.
5662 include_state: An _IncludeState instance in which the headers are inserted.
5663 function_state: A _FunctionState instance which counts function lines, etc.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005664 nesting_state: A NestingState instance which maintains information about
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005665 the current stack of nested blocks being parsed.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005666 error: A callable to which errors are reported, which takes 4 arguments:
5667 filename, line number, error level, and message
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005668 extra_check_functions: An array of additional check functions that will be
5669 run on each source line. Each function takes 4
5670 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005671 """
5672 raw_lines = clean_lines.raw_lines
erg@google.com35589e62010-11-17 18:58:16 +00005673 ParseNolintSuppressions(filename, raw_lines[line], line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005674 nesting_state.Update(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005675 CheckForNamespaceIndentation(filename, nesting_state, clean_lines, line,
5676 error)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005677 if nesting_state.InAsmBlock(): return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005678 CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005679 CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005680 CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005681 CheckLanguage(filename, clean_lines, line, file_extension, include_state,
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005682 nesting_state, error)
5683 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005684 CheckForNonStandardConstructs(filename, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005685 nesting_state, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005686 CheckVlogArguments(filename, clean_lines, line, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005687 CheckPosixThreading(filename, clean_lines, line, error)
erg@google.com6317a9c2009-06-25 00:28:19 +00005688 CheckInvalidIncrement(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005689 CheckMakePairUsesDeduction(filename, clean_lines, line, error)
avakulenko@google.com59146752014-08-11 20:20:55 +00005690 CheckRedundantVirtual(filename, clean_lines, line, error)
5691 CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005692 for check_fn in extra_check_functions:
5693 check_fn(filename, clean_lines, line, error)
avakulenko@google.com17449932014-07-28 22:13:33 +00005694
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005695def FlagCxx11Features(filename, clean_lines, linenum, error):
5696 """Flag those c++11 features that we only allow in certain places.
5697
5698 Args:
5699 filename: The name of the current file.
5700 clean_lines: A CleansedLines instance containing the file.
5701 linenum: The number of the line to check.
5702 error: The function to call with any errors found.
5703 """
5704 line = clean_lines.elided[linenum]
5705
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005706 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005707
5708 # Flag unapproved C++ TR1 headers.
5709 if include and include.group(1).startswith('tr1/'):
5710 error(filename, linenum, 'build/c++tr1', 5,
5711 ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
5712
5713 # Flag unapproved C++11 headers.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005714 if include and include.group(1) in ('cfenv',
5715 'condition_variable',
5716 'fenv.h',
5717 'future',
5718 'mutex',
5719 'thread',
5720 'chrono',
5721 'ratio',
5722 'regex',
5723 'system_error',
5724 ):
5725 error(filename, linenum, 'build/c++11', 5,
5726 ('<%s> is an unapproved C++11 header.') % include.group(1))
5727
5728 # The only place where we need to worry about C++11 keywords and library
5729 # features in preprocessor directives is in macro definitions.
5730 if Match(r'\s*#', line) and not Match(r'\s*#\s*define\b', line): return
5731
5732 # These are classes and free functions. The classes are always
5733 # mentioned as std::*, but we only catch the free functions if
5734 # they're not found by ADL. They're alphabetical by header.
5735 for top_name in (
5736 # type_traits
5737 'alignment_of',
5738 'aligned_union',
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005739 ):
5740 if Search(r'\bstd::%s\b' % top_name, line):
5741 error(filename, linenum, 'build/c++11', 5,
5742 ('std::%s is an unapproved C++11 class or function. Send c-style '
5743 'an example of where it would make your code more readable, and '
5744 'they may let you use it.') % top_name)
5745
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005746
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005747def FlagCxx14Features(filename, clean_lines, linenum, error):
5748 """Flag those C++14 features that we restrict.
5749
5750 Args:
5751 filename: The name of the current file.
5752 clean_lines: A CleansedLines instance containing the file.
5753 linenum: The number of the line to check.
5754 error: The function to call with any errors found.
5755 """
5756 line = clean_lines.elided[linenum]
5757
5758 include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5759
5760 # Flag unapproved C++14 headers.
5761 if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
5762 error(filename, linenum, 'build/c++14', 5,
5763 ('<%s> is an unapproved C++14 header.') % include.group(1))
5764
5765
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005766def ProcessFileData(filename, file_extension, lines, error,
5767 extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005768 """Performs lint checks and reports any errors to the given error function.
5769
5770 Args:
5771 filename: Filename of the file that is being processed.
5772 file_extension: The extension (dot not included) of the file.
5773 lines: An array of strings, each representing a line of the file, with the
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005774 last element being empty if the file is terminated with a newline.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005775 error: A callable to which errors are reported, which takes 4 arguments:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005776 filename, line number, error level, and message
5777 extra_check_functions: An array of additional check functions that will be
5778 run on each source line. Each function takes 4
5779 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005780 """
5781 lines = (['// marker so line numbers and indices both start at 1'] + lines +
5782 ['// marker so line numbers end in a known way'])
5783
5784 include_state = _IncludeState()
5785 function_state = _FunctionState()
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005786 nesting_state = NestingState()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005787
erg@google.com35589e62010-11-17 18:58:16 +00005788 ResetNolintSuppressions()
5789
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005790 CheckForCopyright(filename, lines, error)
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005791 ProcessGlobalSuppresions(lines)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005792 RemoveMultiLineComments(filename, lines, error)
5793 clean_lines = CleansedLines(lines)
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005794
5795 if file_extension == 'h':
5796 CheckForHeaderGuard(filename, clean_lines, error)
5797
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005798 for line in xrange(clean_lines.NumLines()):
5799 ProcessLine(filename, file_extension, clean_lines, line,
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00005800 include_state, function_state, nesting_state, error,
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005801 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005802 FlagCxx11Features(filename, clean_lines, line, error)
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005803 nesting_state.CheckCompletedBlocks(filename, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005804
5805 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
skym@chromium.org3990c412016-02-05 20:55:12 +00005806
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005807 # Check that the .cc file has included its header if it exists.
avakulenko@chromium.org764ce712016-05-06 23:03:41 +00005808 if _IsSourceExtension(file_extension):
avakulenko@google.com255f2be2014-12-05 22:19:55 +00005809 CheckHeaderFileIncluded(filename, include_state, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005810
5811 # We check here rather than inside ProcessLine so that we see raw
5812 # lines rather than "cleaned" lines.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005813 CheckForBadCharacters(filename, lines, error)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005814
5815 CheckForNewlineAtEOF(filename, lines, error)
5816
avakulenko@google.com17449932014-07-28 22:13:33 +00005817def ProcessConfigOverrides(filename):
5818 """ Loads the configuration files and processes the config overrides.
5819
5820 Args:
5821 filename: The name of the file being processed by the linter.
5822
5823 Returns:
5824 False if the current |filename| should not be processed further.
5825 """
5826
5827 abs_filename = os.path.abspath(filename)
5828 cfg_filters = []
5829 keep_looking = True
5830 while keep_looking:
5831 abs_path, base_name = os.path.split(abs_filename)
5832 if not base_name:
5833 break # Reached the root directory.
5834
5835 cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
5836 abs_filename = abs_path
5837 if not os.path.isfile(cfg_file):
5838 continue
5839
5840 try:
5841 with open(cfg_file) as file_handle:
5842 for line in file_handle:
5843 line, _, _ = line.partition('#') # Remove comments.
5844 if not line.strip():
5845 continue
5846
5847 name, _, val = line.partition('=')
5848 name = name.strip()
5849 val = val.strip()
5850 if name == 'set noparent':
5851 keep_looking = False
5852 elif name == 'filter':
5853 cfg_filters.append(val)
5854 elif name == 'exclude_files':
5855 # When matching exclude_files pattern, use the base_name of
5856 # the current file name or the directory name we are processing.
5857 # For example, if we are checking for lint errors in /foo/bar/baz.cc
5858 # and we found the .cfg file at /foo/CPPLINT.cfg, then the config
5859 # file's "exclude_files" filter is meant to be checked against "bar"
5860 # and not "baz" nor "bar/baz.cc".
5861 if base_name:
5862 pattern = re.compile(val)
5863 if pattern.match(base_name):
5864 sys.stderr.write('Ignoring "%s": file excluded by "%s". '
5865 'File path component "%s" matches '
5866 'pattern "%s"\n' %
5867 (filename, cfg_file, base_name, val))
5868 return False
avakulenko@google.com68a4fa62014-08-25 16:26:18 +00005869 elif name == 'linelength':
5870 global _line_length
5871 try:
5872 _line_length = int(val)
5873 except ValueError:
5874 sys.stderr.write('Line length must be numeric.')
avakulenko@google.com17449932014-07-28 22:13:33 +00005875 else:
5876 sys.stderr.write(
5877 'Invalid configuration option (%s) in file %s\n' %
5878 (name, cfg_file))
5879
5880 except IOError:
5881 sys.stderr.write(
5882 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
5883 keep_looking = False
5884
5885 # Apply all the accumulated filters in reverse order (top-level directory
5886 # config options having the least priority).
5887 for filter in reversed(cfg_filters):
5888 _AddFilters(filter)
5889
5890 return True
5891
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005892
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005893def ProcessFile(filename, vlevel, extra_check_functions=[]):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005894 """Does google-lint on a single file.
5895
5896 Args:
5897 filename: The name of the file to parse.
5898
5899 vlevel: The level of errors to report. Every error of confidence
5900 >= verbose_level will be reported. 0 is a good default.
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005901
5902 extra_check_functions: An array of additional check functions that will be
5903 run on each source line. Each function takes 4
5904 arguments: filename, clean_lines, line, error
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005905 """
5906
5907 _SetVerboseLevel(vlevel)
avakulenko@google.com17449932014-07-28 22:13:33 +00005908 _BackupFilters()
5909
5910 if not ProcessConfigOverrides(filename):
5911 _RestoreFilters()
5912 return
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005913
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005914 lf_lines = []
5915 crlf_lines = []
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005916 try:
5917 # Support the UNIX convention of using "-" for stdin. Note that
5918 # we are not opening the file with universal newline support
5919 # (which codecs doesn't support anyway), so the resulting lines do
5920 # contain trailing '\r' characters if we are reading a file that
5921 # has CRLF endings.
5922 # If after the split a trailing '\r' is present, it is removed
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005923 # below.
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005924 if filename == '-':
5925 lines = codecs.StreamReaderWriter(sys.stdin,
5926 codecs.getreader('utf8'),
5927 codecs.getwriter('utf8'),
5928 'replace').read().split('\n')
5929 else:
5930 lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
5931
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005932 # Remove trailing '\r'.
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005933 # The -1 accounts for the extra trailing blank line we get from split()
5934 for linenum in range(len(lines) - 1):
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005935 if lines[linenum].endswith('\r'):
5936 lines[linenum] = lines[linenum].rstrip('\r')
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005937 crlf_lines.append(linenum + 1)
5938 else:
5939 lf_lines.append(linenum + 1)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005940
5941 except IOError:
5942 sys.stderr.write(
5943 "Skipping input '%s': Can't open for reading\n" % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00005944 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005945 return
5946
5947 # Note, if no dot is found, this will give the entire filename as the ext.
5948 file_extension = filename[filename.rfind('.') + 1:]
5949
5950 # When reading from stdin, the extension is unknown, so no cpplint tests
5951 # should rely on the extension.
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00005952 if filename != '-' and file_extension not in _valid_extensions:
5953 sys.stderr.write('Ignoring %s; not a valid file name '
5954 '(%s)\n' % (filename, ', '.join(_valid_extensions)))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005955 else:
asvitkine@chromium.org8b8d8be2011-09-08 15:34:45 +00005956 ProcessFileData(filename, file_extension, lines, Error,
5957 extra_check_functions)
avakulenko@google.comd39bbb52014-06-04 22:55:20 +00005958
5959 # If end-of-line sequences are a mix of LF and CR-LF, issue
5960 # warnings on the lines with CR.
5961 #
5962 # Don't issue any warnings if all lines are uniformly LF or CR-LF,
5963 # since critique can handle these just fine, and the style guide
5964 # doesn't dictate a particular end of line sequence.
5965 #
5966 # We can't depend on os.linesep to determine what the desired
5967 # end-of-line sequence should be, since that will return the
5968 # server-side end-of-line sequence.
5969 if lf_lines and crlf_lines:
5970 # Warn on every line with CR. An alternative approach might be to
5971 # check whether the file is mostly CRLF or just LF, and warn on the
5972 # minority, we bias toward LF here since most tools prefer LF.
5973 for linenum in crlf_lines:
5974 Error(filename, linenum, 'whitespace/newline', 1,
5975 'Unexpected \\r (^M) found; better to use only \\n')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005976
5977 sys.stderr.write('Done processing %s\n' % filename)
avakulenko@google.com17449932014-07-28 22:13:33 +00005978 _RestoreFilters()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00005979
5980
5981def PrintUsage(message):
5982 """Prints a brief usage string and exits, optionally with an error message.
5983
5984 Args:
5985 message: The optional error message.
5986 """
5987 sys.stderr.write(_USAGE)
5988 if message:
5989 sys.exit('\nFATAL ERROR: ' + message)
5990 else:
5991 sys.exit(1)
5992
5993
5994def PrintCategories():
5995 """Prints a list of all the error-categories used by error messages.
5996
5997 These are the categories used to filter messages via --filter.
5998 """
erg@google.com35589e62010-11-17 18:58:16 +00005999 sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES))
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006000 sys.exit(0)
6001
6002
6003def ParseArguments(args):
6004 """Parses the command line arguments.
6005
6006 This may set the output format and verbosity level as side-effects.
6007
6008 Args:
6009 args: The command line arguments:
6010
6011 Returns:
6012 The list of filenames to lint.
6013 """
6014 try:
6015 (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
erg@google.com26970fa2009-11-17 18:07:32 +00006016 'counting=',
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006017 'filter=',
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006018 'root=',
6019 'linelength=',
6020 'extensions='])
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006021 except getopt.GetoptError:
6022 PrintUsage('Invalid arguments.')
6023
6024 verbosity = _VerboseLevel()
6025 output_format = _OutputFormat()
6026 filters = ''
erg@google.com26970fa2009-11-17 18:07:32 +00006027 counting_style = ''
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006028
6029 for (opt, val) in opts:
6030 if opt == '--help':
6031 PrintUsage(None)
6032 elif opt == '--output':
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006033 if val not in ('emacs', 'vs7', 'eclipse'):
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006034 PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006035 output_format = val
6036 elif opt == '--verbose':
6037 verbosity = int(val)
6038 elif opt == '--filter':
6039 filters = val
erg@google.com6317a9c2009-06-25 00:28:19 +00006040 if not filters:
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006041 PrintCategories()
erg@google.com26970fa2009-11-17 18:07:32 +00006042 elif opt == '--counting':
6043 if val not in ('total', 'toplevel', 'detailed'):
6044 PrintUsage('Valid counting options are total, toplevel, and detailed')
6045 counting_style = val
mazda@chromium.org3fffcec2013-06-07 01:04:53 +00006046 elif opt == '--root':
6047 global _root
6048 _root = val
raphael.kubo.da.costa@intel.com331fbc42014-05-09 08:48:20 +00006049 elif opt == '--linelength':
6050 global _line_length
6051 try:
6052 _line_length = int(val)
6053 except ValueError:
6054 PrintUsage('Line length must be digits.')
6055 elif opt == '--extensions':
6056 global _valid_extensions
6057 try:
6058 _valid_extensions = set(val.split(','))
6059 except ValueError:
6060 PrintUsage('Extensions must be comma seperated list.')
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006061
6062 if not filenames:
6063 PrintUsage('No files were specified.')
6064
6065 _SetOutputFormat(output_format)
6066 _SetVerboseLevel(verbosity)
6067 _SetFilters(filters)
erg@google.com26970fa2009-11-17 18:07:32 +00006068 _SetCountingStyle(counting_style)
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006069
6070 return filenames
6071
6072
6073def main():
6074 filenames = ParseArguments(sys.argv[1:])
6075
6076 # Change stderr to write with replacement characters so we don't die
6077 # if we try to print something containing non-ASCII characters.
6078 sys.stderr = codecs.StreamReaderWriter(sys.stderr,
6079 codecs.getreader('utf8'),
6080 codecs.getwriter('utf8'),
6081 'replace')
6082
erg@google.com26970fa2009-11-17 18:07:32 +00006083 _cpplint_state.ResetErrorCounts()
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006084 for filename in filenames:
6085 ProcessFile(filename, _cpplint_state.verbose_level)
erg@google.com26970fa2009-11-17 18:07:32 +00006086 _cpplint_state.PrintErrorCounts()
6087
maruel@google.comfb2b8eb2009-04-23 21:03:42 +00006088 sys.exit(_cpplint_state.error_count > 0)
6089
6090
6091if __name__ == '__main__':
6092 main()