~plane1/maus/devel_624

« back to all changes in this revision

Viewing changes to third_party/google-styleguide/cpplint/.svn/text-base/cpplint.py.svn-base

  • Committer: tunnell
  • Date: 2010-09-30 13:56:05 UTC
  • Revision ID: tunnell@itchy-20100930135605-wxbkfgy75p0sndk3
add third party

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python2.4
 
2
#
 
3
# Copyright (c) 2009 Google Inc. All rights reserved.
 
4
#
 
5
# Redistribution and use in source and binary forms, with or without
 
6
# modification, are permitted provided that the following conditions are
 
7
# met:
 
8
#
 
9
#    * 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.
 
18
#
 
19
# 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.
 
30
 
 
31
# Here are some issues that I've had people identify in my code during reviews,
 
32
# that I think are possible to flag automatically in a lint tool.  If these were
 
33
# caught by lint, it would save time both for myself and that of my reviewers.
 
34
# Most likely, some of these are beyond the scope of the current lint framework,
 
35
# but I think it is valuable to retain these wish-list items even if they cannot
 
36
# be immediately implemented.
 
37
#
 
38
#  Suggestions
 
39
#  -----------
 
40
#  - Check for no 'explicit' for multi-arg ctor
 
41
#  - Check for boolean assign RHS in parens
 
42
#  - Check for ctor initializer-list colon position and spacing
 
43
#  - Check that if there's a ctor, there should be a dtor
 
44
#  - Check accessors that return non-pointer member variables are
 
45
#    declared const
 
46
#  - Check accessors that return non-const pointer member vars are
 
47
#    *not* declared const
 
48
#  - Check for using public includes for testing
 
49
#  - Check for spaces between brackets in one-line inline method
 
50
#  - Check for no assert()
 
51
#  - Check for spaces surrounding operators
 
52
#  - Check for 0 in pointer context (should be NULL)
 
53
#  - Check for 0 in char context (should be '\0')
 
54
#  - Check for camel-case method name conventions for methods
 
55
#    that are not simple inline getters and setters
 
56
#  - Check that base classes have virtual destructors
 
57
#    put "  // namespace" after } that closes a namespace, with
 
58
#    namespace's name after 'namespace' if it is named.
 
59
#  - Do not indent namespace contents
 
60
#  - Avoid inlining non-trivial constructors in header files
 
61
#    include base/basictypes.h if DISALLOW_EVIL_CONSTRUCTORS is used
 
62
#  - Check for old-school (void) cast for call-sites of functions
 
63
#    ignored return value
 
64
#  - Check gUnit usage of anonymous namespace
 
65
#  - Check for class declaration order (typedefs, consts, enums,
 
66
#    ctor(s?), dtor, friend declarations, methods, member vars)
 
67
#
 
68
 
 
69
"""Does google-lint on c++ files.
 
70
 
 
71
The goal of this script is to identify places in the code that *may*
 
72
be in non-compliance with google style.  It does not attempt to fix
 
73
up these problems -- the point is to educate.  It does also not
 
74
attempt to find all problems, or to ensure that everything it does
 
75
find is legitimately a problem.
 
76
 
 
77
In particular, we can get very confused by /* and // inside strings!
 
78
We do a small hack, which is to ignore //'s with "'s after them on the
 
79
same line, but it is far from perfect (in either direction).
 
80
"""
 
81
 
 
82
import codecs
 
83
import getopt
 
84
import math  # for log
 
85
import os
 
86
import re
 
87
import sre_compile
 
88
import string
 
89
import sys
 
90
import unicodedata
 
91
 
 
92
 
 
93
_USAGE = """
 
94
Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
 
95
                   [--counting=total|toplevel|detailed]
 
96
        <file> [file] ...
 
97
 
 
98
  The style guidelines this tries to follow are those in
 
99
    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
 
100
 
 
101
  Every problem is given a confidence score from 1-5, with 5 meaning we are
 
102
  certain of the problem, and 1 meaning it could be a legitimate construct.
 
103
  This will miss some errors, and is not a substitute for a code review.
 
104
 
 
105
  To suppress false-positive errors of a certain category, add a
 
106
  'NOLINT(category)' comment to the line.  NOLINT or NOLINT(*)
 
107
  suppresses errors of all categories on that line.
 
108
 
 
109
  The files passed in will be linted; at least one file must be provided.
 
110
  Linted extensions are .cc, .cpp, and .h.  Other file types will be ignored.
 
111
 
 
112
  Flags:
 
113
 
 
114
    output=vs7
 
115
      By default, the output is formatted to ease emacs parsing.  Visual Studio
 
116
      compatible output (vs7) may also be used.  Other formats are unsupported.
 
117
 
 
118
    verbose=#
 
119
      Specify a number 0-5 to restrict errors to certain verbosity levels.
 
120
 
 
121
    filter=-x,+y,...
 
122
      Specify a comma-separated list of category-filters to apply: only
 
123
      error messages whose category names pass the filters will be printed.
 
124
      (Category names are printed with the message and look like
 
125
      "[whitespace/indent]".)  Filters are evaluated left to right.
 
126
      "-FOO" and "FOO" means "do not print categories that start with FOO".
 
127
      "+FOO" means "do print categories that start with FOO".
 
128
 
 
129
      Examples: --filter=-whitespace,+whitespace/braces
 
130
                --filter=whitespace,runtime/printf,+runtime/printf_format
 
131
                --filter=-,+build/include_what_you_use
 
132
 
 
133
      To see a list of all the categories used in cpplint, pass no arg:
 
134
         --filter=
 
135
 
 
136
    counting=total|toplevel|detailed
 
137
      The total number of errors found is always printed. If
 
138
      'toplevel' is provided, then the count of errors in each of
 
139
      the top-level categories like 'build' and 'whitespace' will
 
140
      also be printed. If 'detailed' is provided, then a count
 
141
      is provided for each category like 'build/class'.
 
142
"""
 
143
 
 
144
# We categorize each error message we print.  Here are the categories.
 
145
# We want an explicit list so we can list them all in cpplint --filter=.
 
146
# If you add a new error message with a new category, add it to the list
 
147
# here!  cpplint_unittest.py should tell you if you forget to do this.
 
148
# \ used for clearer layout -- pylint: disable-msg=C6013
 
149
_ERROR_CATEGORIES = [
 
150
  'build/class',
 
151
  'build/deprecated',
 
152
  'build/endif_comment',
 
153
  'build/forward_decl',
 
154
  'build/header_guard',
 
155
  'build/include',
 
156
  'build/include_alpha',
 
157
  'build/include_order',
 
158
  'build/include_what_you_use',
 
159
  'build/namespaces',
 
160
  'build/printf_format',
 
161
  'build/storage_class',
 
162
  'legal/copyright',
 
163
  'readability/braces',
 
164
  'readability/casting',
 
165
  'readability/check',
 
166
  'readability/constructors',
 
167
  'readability/fn_size',
 
168
  'readability/function',
 
169
  'readability/multiline_comment',
 
170
  'readability/multiline_string',
 
171
  'readability/nolint',
 
172
  'readability/streams',
 
173
  'readability/todo',
 
174
  'readability/utf8',
 
175
  'runtime/arrays',
 
176
  'runtime/casting',
 
177
  'runtime/explicit',
 
178
  'runtime/int',
 
179
  'runtime/init',
 
180
  'runtime/invalid_increment',
 
181
  'runtime/member_string_references',
 
182
  'runtime/memset',
 
183
  'runtime/operator',
 
184
  'runtime/printf',
 
185
  'runtime/printf_format',
 
186
  'runtime/references',
 
187
  'runtime/rtti',
 
188
  'runtime/sizeof',
 
189
  'runtime/string',
 
190
  'runtime/threadsafe_fn',
 
191
  'runtime/virtual',
 
192
  'whitespace/blank_line',
 
193
  'whitespace/braces',
 
194
  'whitespace/comma',
 
195
  'whitespace/comments',
 
196
  'whitespace/end_of_line',
 
197
  'whitespace/ending_newline',
 
198
  'whitespace/indent',
 
199
  'whitespace/labels',
 
200
  'whitespace/line_length',
 
201
  'whitespace/newline',
 
202
  'whitespace/operators',
 
203
  'whitespace/parens',
 
204
  'whitespace/semicolon',
 
205
  'whitespace/tab',
 
206
  'whitespace/todo'
 
207
  ]
 
208
 
 
209
# The default state of the category filter. This is overrided by the --filter=
 
210
# flag. By default all errors are on, so only add here categories that should be
 
211
# off by default (i.e., categories that must be enabled by the --filter= flags).
 
212
# All entries here should start with a '-' or '+', as in the --filter= flag.
 
213
_DEFAULT_FILTERS = [ '-build/include_alpha' ]
 
214
 
 
215
# We used to check for high-bit characters, but after much discussion we
 
216
# decided those were OK, as long as they were in UTF-8 and didn't represent
 
217
# hard-coded international strings, which belong in a seperate i18n file.
 
218
 
 
219
# Headers that we consider STL headers.
 
220
_STL_HEADERS = frozenset([
 
221
    'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
 
222
    'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
 
223
    'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new',
 
224
    'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',
 
225
    'stl_alloc.h', 'stl_relops.h', 'type_traits.h',
 
226
    'utility', 'vector', 'vector.h',
 
227
    ])
 
228
 
 
229
 
 
230
# Non-STL C++ system headers.
 
231
_CPP_HEADERS = frozenset([
 
232
    'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype',
 
233
    'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath',
 
234
    'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef',
 
235
    'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype',
 
236
    'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream',
 
237
    'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip',
 
238
    'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h',
 
239
    'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h',
 
240
    'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h',
 
241
    'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h',
 
242
    'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',
 
243
    'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string',
 
244
    'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray',
 
245
    ])
 
246
 
 
247
 
 
248
# Assertion macros.  These are defined in base/logging.h and
 
249
# testing/base/gunit.h.  Note that the _M versions need to come first
 
250
# for substring matching to work.
 
251
_CHECK_MACROS = [
 
252
    'DCHECK', 'CHECK',
 
253
    'EXPECT_TRUE_M', 'EXPECT_TRUE',
 
254
    'ASSERT_TRUE_M', 'ASSERT_TRUE',
 
255
    'EXPECT_FALSE_M', 'EXPECT_FALSE',
 
256
    'ASSERT_FALSE_M', 'ASSERT_FALSE',
 
257
    ]
 
258
 
 
259
# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
 
260
_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
 
261
 
 
262
for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
 
263
                        ('>=', 'GE'), ('>', 'GT'),
 
264
                        ('<=', 'LE'), ('<', 'LT')]:
 
265
  _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
 
266
  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
 
267
  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
 
268
  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
 
269
  _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
 
270
  _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
 
271
 
 
272
for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
 
273
                            ('>=', 'LT'), ('>', 'LE'),
 
274
                            ('<=', 'GT'), ('<', 'GE')]:
 
275
  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
 
276
  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
 
277
  _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
 
278
  _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
 
279
 
 
280
 
 
281
# These constants define types of headers for use with
 
282
# _IncludeState.CheckNextIncludeOrder().
 
283
_C_SYS_HEADER = 1
 
284
_CPP_SYS_HEADER = 2
 
285
_LIKELY_MY_HEADER = 3
 
286
_POSSIBLE_MY_HEADER = 4
 
287
_OTHER_HEADER = 5
 
288
 
 
289
 
 
290
_regexp_compile_cache = {}
 
291
 
 
292
# Finds occurrences of NOLINT or NOLINT(...).
 
293
_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?')
 
294
 
 
295
# {str, set(int)}: a map from error categories to sets of linenumbers
 
296
# on which those errors are expected and should be suppressed.
 
297
_error_suppressions = {}
 
298
 
 
299
def ParseNolintSuppressions(filename, raw_line, linenum, error):
 
300
  """Updates the global list of error-suppressions.
 
301
 
 
302
  Parses any NOLINT comments on the current line, updating the global
 
303
  error_suppressions store.  Reports an error if the NOLINT comment
 
304
  was malformed.
 
305
 
 
306
  Args:
 
307
    filename: str, the name of the input file.
 
308
    raw_line: str, the line of input text, with comments.
 
309
    linenum: int, the number of the current line.
 
310
    error: function, an error handler.
 
311
  """
 
312
  # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*).
 
313
  m = _RE_SUPPRESSION.search(raw_line)
 
314
  if m:
 
315
    category = m.group(1)
 
316
    if category in (None, '(*)'):  # => "suppress all"
 
317
      _error_suppressions.setdefault(None, set()).add(linenum)
 
318
    else:
 
319
      if category.startswith('(') and category.endswith(')'):
 
320
        category = category[1:-1]
 
321
        if category in _ERROR_CATEGORIES:
 
322
          _error_suppressions.setdefault(category, set()).add(linenum)
 
323
        else:
 
324
          error(filename, linenum, 'readability/nolint', 5,
 
325
            'Unknown NOLINT error category: %s' % category)
 
326
 
 
327
 
 
328
def ResetNolintSuppressions():
 
329
  "Resets the set of NOLINT suppressions to empty."
 
330
  _error_suppressions.clear()
 
331
 
 
332
 
 
333
def IsErrorSuppressedByNolint(category, linenum):
 
334
  """Returns true if the specified error category is suppressed on this line.
 
335
 
 
336
  Consults the global error_suppressions map populated by
 
337
  ParseNolintSuppressions/ResetNolintSuppressions.
 
338
 
 
339
  Args:
 
340
    category: str, the category of the error.
 
341
    linenum: int, the current line number.
 
342
  Returns:
 
343
    bool, True iff the error should be suppressed due to a NOLINT comment.
 
344
  """
 
345
  return (linenum in _error_suppressions.get(category, set()) or
 
346
          linenum in _error_suppressions.get(None, set()))
 
347
 
 
348
def Match(pattern, s):
 
349
  """Matches the string with the pattern, caching the compiled regexp."""
 
350
  # The regexp compilation caching is inlined in both Match and Search for
 
351
  # performance reasons; factoring it out into a separate function turns out
 
352
  # to be noticeably expensive.
 
353
  if not pattern in _regexp_compile_cache:
 
354
    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
 
355
  return _regexp_compile_cache[pattern].match(s)
 
356
 
 
357
 
 
358
def Search(pattern, s):
 
359
  """Searches the string for the pattern, caching the compiled regexp."""
 
360
  if not pattern in _regexp_compile_cache:
 
361
    _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
 
362
  return _regexp_compile_cache[pattern].search(s)
 
363
 
 
364
 
 
365
class _IncludeState(dict):
 
366
  """Tracks line numbers for includes, and the order in which includes appear.
 
367
 
 
368
  As a dict, an _IncludeState object serves as a mapping between include
 
369
  filename and line number on which that file was included.
 
370
 
 
371
  Call CheckNextIncludeOrder() once for each header in the file, passing
 
372
  in the type constants defined above. Calls in an illegal order will
 
373
  raise an _IncludeError with an appropriate error message.
 
374
 
 
375
  """
 
376
  # self._section will move monotonically through this set. If it ever
 
377
  # needs to move backwards, CheckNextIncludeOrder will raise an error.
 
378
  _INITIAL_SECTION = 0
 
379
  _MY_H_SECTION = 1
 
380
  _C_SECTION = 2
 
381
  _CPP_SECTION = 3
 
382
  _OTHER_H_SECTION = 4
 
383
 
 
384
  _TYPE_NAMES = {
 
385
      _C_SYS_HEADER: 'C system header',
 
386
      _CPP_SYS_HEADER: 'C++ system header',
 
387
      _LIKELY_MY_HEADER: 'header this file implements',
 
388
      _POSSIBLE_MY_HEADER: 'header this file may implement',
 
389
      _OTHER_HEADER: 'other header',
 
390
      }
 
391
  _SECTION_NAMES = {
 
392
      _INITIAL_SECTION: "... nothing. (This can't be an error.)",
 
393
      _MY_H_SECTION: 'a header this file implements',
 
394
      _C_SECTION: 'C system header',
 
395
      _CPP_SECTION: 'C++ system header',
 
396
      _OTHER_H_SECTION: 'other header',
 
397
      }
 
398
 
 
399
  def __init__(self):
 
400
    dict.__init__(self)
 
401
    # The name of the current section.
 
402
    self._section = self._INITIAL_SECTION
 
403
    # The path of last found header.
 
404
    self._last_header = ''
 
405
 
 
406
  def CanonicalizeAlphabeticalOrder(self, header_path):
 
407
    """Returns a path canonicalized for alphabetical comparisson.
 
408
 
 
409
    - replaces "-" with "_" so they both cmp the same.
 
410
    - removes '-inl' since we don't require them to be after the main header.
 
411
    - lowercase everything, just in case.
 
412
 
 
413
    Args:
 
414
      header_path: Path to be canonicalized.
 
415
 
 
416
    Returns:
 
417
      Canonicalized path.
 
418
    """
 
419
    return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
 
420
 
 
421
  def IsInAlphabeticalOrder(self, header_path):
 
422
    """Check if a header is in alphabetical order with the previous header.
 
423
 
 
424
    Args:
 
425
      header_path: Header to be checked.
 
426
 
 
427
    Returns:
 
428
      Returns true if the header is in alphabetical order.
 
429
    """
 
430
    canonical_header = self.CanonicalizeAlphabeticalOrder(header_path)
 
431
    if self._last_header > canonical_header:
 
432
      return False
 
433
    self._last_header = canonical_header
 
434
    return True
 
435
 
 
436
  def CheckNextIncludeOrder(self, header_type):
 
437
    """Returns a non-empty error message if the next header is out of order.
 
438
 
 
439
    This function also updates the internal state to be ready to check
 
440
    the next include.
 
441
 
 
442
    Args:
 
443
      header_type: One of the _XXX_HEADER constants defined above.
 
444
 
 
445
    Returns:
 
446
      The empty string if the header is in the right order, or an
 
447
      error message describing what's wrong.
 
448
 
 
449
    """
 
450
    error_message = ('Found %s after %s' %
 
451
                     (self._TYPE_NAMES[header_type],
 
452
                      self._SECTION_NAMES[self._section]))
 
453
 
 
454
    last_section = self._section
 
455
 
 
456
    if header_type == _C_SYS_HEADER:
 
457
      if self._section <= self._C_SECTION:
 
458
        self._section = self._C_SECTION
 
459
      else:
 
460
        self._last_header = ''
 
461
        return error_message
 
462
    elif header_type == _CPP_SYS_HEADER:
 
463
      if self._section <= self._CPP_SECTION:
 
464
        self._section = self._CPP_SECTION
 
465
      else:
 
466
        self._last_header = ''
 
467
        return error_message
 
468
    elif header_type == _LIKELY_MY_HEADER:
 
469
      if self._section <= self._MY_H_SECTION:
 
470
        self._section = self._MY_H_SECTION
 
471
      else:
 
472
        self._section = self._OTHER_H_SECTION
 
473
    elif header_type == _POSSIBLE_MY_HEADER:
 
474
      if self._section <= self._MY_H_SECTION:
 
475
        self._section = self._MY_H_SECTION
 
476
      else:
 
477
        # This will always be the fallback because we're not sure
 
478
        # enough that the header is associated with this file.
 
479
        self._section = self._OTHER_H_SECTION
 
480
    else:
 
481
      assert header_type == _OTHER_HEADER
 
482
      self._section = self._OTHER_H_SECTION
 
483
 
 
484
    if last_section != self._section:
 
485
      self._last_header = ''
 
486
 
 
487
    return ''
 
488
 
 
489
 
 
490
class _CppLintState(object):
 
491
  """Maintains module-wide state.."""
 
492
 
 
493
  def __init__(self):
 
494
    self.verbose_level = 1  # global setting.
 
495
    self.error_count = 0    # global count of reported errors
 
496
    # filters to apply when emitting error messages
 
497
    self.filters = _DEFAULT_FILTERS[:]
 
498
    self.counting = 'total'  # In what way are we counting errors?
 
499
    self.errors_by_category = {}  # string to int dict storing error counts
 
500
 
 
501
    # output format:
 
502
    # "emacs" - format that emacs can parse (default)
 
503
    # "vs7" - format that Microsoft Visual Studio 7 can parse
 
504
    self.output_format = 'emacs'
 
505
 
 
506
  def SetOutputFormat(self, output_format):
 
507
    """Sets the output format for errors."""
 
508
    self.output_format = output_format
 
509
 
 
510
  def SetVerboseLevel(self, level):
 
511
    """Sets the module's verbosity, and returns the previous setting."""
 
512
    last_verbose_level = self.verbose_level
 
513
    self.verbose_level = level
 
514
    return last_verbose_level
 
515
 
 
516
  def SetCountingStyle(self, counting_style):
 
517
    """Sets the module's counting options."""
 
518
    self.counting = counting_style
 
519
 
 
520
  def SetFilters(self, filters):
 
521
    """Sets the error-message filters.
 
522
 
 
523
    These filters are applied when deciding whether to emit a given
 
524
    error message.
 
525
 
 
526
    Args:
 
527
      filters: A string of comma-separated filters (eg "+whitespace/indent").
 
528
               Each filter should start with + or -; else we die.
 
529
 
 
530
    Raises:
 
531
      ValueError: The comma-separated filters did not all start with '+' or '-'.
 
532
                  E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
 
533
    """
 
534
    # Default filters always have less priority than the flag ones.
 
535
    self.filters = _DEFAULT_FILTERS[:]
 
536
    for filt in filters.split(','):
 
537
      clean_filt = filt.strip()
 
538
      if clean_filt:
 
539
        self.filters.append(clean_filt)
 
540
    for filt in self.filters:
 
541
      if not (filt.startswith('+') or filt.startswith('-')):
 
542
        raise ValueError('Every filter in --filters must start with + or -'
 
543
                         ' (%s does not)' % filt)
 
544
 
 
545
  def ResetErrorCounts(self):
 
546
    """Sets the module's error statistic back to zero."""
 
547
    self.error_count = 0
 
548
    self.errors_by_category = {}
 
549
 
 
550
  def IncrementErrorCount(self, category):
 
551
    """Bumps the module's error statistic."""
 
552
    self.error_count += 1
 
553
    if self.counting in ('toplevel', 'detailed'):
 
554
      if self.counting != 'detailed':
 
555
        category = category.split('/')[0]
 
556
      if category not in self.errors_by_category:
 
557
        self.errors_by_category[category] = 0
 
558
      self.errors_by_category[category] += 1
 
559
 
 
560
  def PrintErrorCounts(self):
 
561
    """Print a summary of errors by category, and the total."""
 
562
    for category, count in self.errors_by_category.iteritems():
 
563
      sys.stderr.write('Category \'%s\' errors found: %d\n' %
 
564
                       (category, count))
 
565
    sys.stderr.write('Total errors found: %d\n' % self.error_count)
 
566
 
 
567
_cpplint_state = _CppLintState()
 
568
 
 
569
 
 
570
def _OutputFormat():
 
571
  """Gets the module's output format."""
 
572
  return _cpplint_state.output_format
 
573
 
 
574
 
 
575
def _SetOutputFormat(output_format):
 
576
  """Sets the module's output format."""
 
577
  _cpplint_state.SetOutputFormat(output_format)
 
578
 
 
579
 
 
580
def _VerboseLevel():
 
581
  """Returns the module's verbosity setting."""
 
582
  return _cpplint_state.verbose_level
 
583
 
 
584
 
 
585
def _SetVerboseLevel(level):
 
586
  """Sets the module's verbosity, and returns the previous setting."""
 
587
  return _cpplint_state.SetVerboseLevel(level)
 
588
 
 
589
 
 
590
def _SetCountingStyle(level):
 
591
  """Sets the module's counting options."""
 
592
  _cpplint_state.SetCountingStyle(level)
 
593
 
 
594
 
 
595
def _Filters():
 
596
  """Returns the module's list of output filters, as a list."""
 
597
  return _cpplint_state.filters
 
598
 
 
599
 
 
600
def _SetFilters(filters):
 
601
  """Sets the module's error-message filters.
 
602
 
 
603
  These filters are applied when deciding whether to emit a given
 
604
  error message.
 
605
 
 
606
  Args:
 
607
    filters: A string of comma-separated filters (eg "whitespace/indent").
 
608
             Each filter should start with + or -; else we die.
 
609
  """
 
610
  _cpplint_state.SetFilters(filters)
 
611
 
 
612
 
 
613
class _FunctionState(object):
 
614
  """Tracks current function name and the number of lines in its body."""
 
615
 
 
616
  _NORMAL_TRIGGER = 250  # for --v=0, 500 for --v=1, etc.
 
617
  _TEST_TRIGGER = 400    # about 50% more than _NORMAL_TRIGGER.
 
618
 
 
619
  def __init__(self):
 
620
    self.in_a_function = False
 
621
    self.lines_in_function = 0
 
622
    self.current_function = ''
 
623
 
 
624
  def Begin(self, function_name):
 
625
    """Start analyzing function body.
 
626
 
 
627
    Args:
 
628
      function_name: The name of the function being tracked.
 
629
    """
 
630
    self.in_a_function = True
 
631
    self.lines_in_function = 0
 
632
    self.current_function = function_name
 
633
 
 
634
  def Count(self):
 
635
    """Count line in current function body."""
 
636
    if self.in_a_function:
 
637
      self.lines_in_function += 1
 
638
 
 
639
  def Check(self, error, filename, linenum):
 
640
    """Report if too many lines in function body.
 
641
 
 
642
    Args:
 
643
      error: The function to call with any errors found.
 
644
      filename: The name of the current file.
 
645
      linenum: The number of the line to check.
 
646
    """
 
647
    if Match(r'T(EST|est)', self.current_function):
 
648
      base_trigger = self._TEST_TRIGGER
 
649
    else:
 
650
      base_trigger = self._NORMAL_TRIGGER
 
651
    trigger = base_trigger * 2**_VerboseLevel()
 
652
 
 
653
    if self.lines_in_function > trigger:
 
654
      error_level = int(math.log(self.lines_in_function / base_trigger, 2))
 
655
      # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
 
656
      if error_level > 5:
 
657
        error_level = 5
 
658
      error(filename, linenum, 'readability/fn_size', error_level,
 
659
            'Small and focused functions are preferred:'
 
660
            ' %s has %d non-comment lines'
 
661
            ' (error triggered by exceeding %d lines).'  % (
 
662
                self.current_function, self.lines_in_function, trigger))
 
663
 
 
664
  def End(self):
 
665
    """Stop analizing function body."""
 
666
    self.in_a_function = False
 
667
 
 
668
 
 
669
class _IncludeError(Exception):
 
670
  """Indicates a problem with the include order in a file."""
 
671
  pass
 
672
 
 
673
 
 
674
class FileInfo:
 
675
  """Provides utility functions for filenames.
 
676
 
 
677
  FileInfo provides easy access to the components of a file's path
 
678
  relative to the project root.
 
679
  """
 
680
 
 
681
  def __init__(self, filename):
 
682
    self._filename = filename
 
683
 
 
684
  def FullName(self):
 
685
    """Make Windows paths like Unix."""
 
686
    return os.path.abspath(self._filename).replace('\\', '/')
 
687
 
 
688
  def RepositoryName(self):
 
689
    """FullName after removing the local path to the repository.
 
690
 
 
691
    If we have a real absolute path name here we can try to do something smart:
 
692
    detecting the root of the checkout and truncating /path/to/checkout from
 
693
    the name so that we get header guards that don't include things like
 
694
    "C:\Documents and Settings\..." or "/home/username/..." in them and thus
 
695
    people on different computers who have checked the source out to different
 
696
    locations won't see bogus errors.
 
697
    """
 
698
    fullname = self.FullName()
 
699
 
 
700
    if os.path.exists(fullname):
 
701
      project_dir = os.path.dirname(fullname)
 
702
 
 
703
      if os.path.exists(os.path.join(project_dir, ".svn")):
 
704
        # If there's a .svn file in the current directory, we recursively look
 
705
        # up the directory tree for the top of the SVN checkout
 
706
        root_dir = project_dir
 
707
        one_up_dir = os.path.dirname(root_dir)
 
708
        while os.path.exists(os.path.join(one_up_dir, ".svn")):
 
709
          root_dir = os.path.dirname(root_dir)
 
710
          one_up_dir = os.path.dirname(one_up_dir)
 
711
 
 
712
        prefix = os.path.commonprefix([root_dir, project_dir])
 
713
        return fullname[len(prefix) + 1:]
 
714
 
 
715
      # Not SVN? Try to find a git or hg top level directory by searching up
 
716
      # from the current path.
 
717
      root_dir = os.path.dirname(fullname)
 
718
      while (root_dir != os.path.dirname(root_dir) and
 
719
             not os.path.exists(os.path.join(root_dir, ".git")) and
 
720
             not os.path.exists(os.path.join(root_dir, ".hg"))):
 
721
        root_dir = os.path.dirname(root_dir)
 
722
        if (os.path.exists(os.path.join(root_dir, ".git")) or
 
723
            os.path.exists(os.path.join(root_dir, ".hg"))):
 
724
          prefix = os.path.commonprefix([root_dir, project_dir])
 
725
          return fullname[len(prefix) + 1:]
 
726
 
 
727
    # Don't know what to do; header guard warnings may be wrong...
 
728
    return fullname
 
729
 
 
730
  def Split(self):
 
731
    """Splits the file into the directory, basename, and extension.
 
732
 
 
733
    For 'chrome/browser/browser.cc', Split() would
 
734
    return ('chrome/browser', 'browser', '.cc')
 
735
 
 
736
    Returns:
 
737
      A tuple of (directory, basename, extension).
 
738
    """
 
739
 
 
740
    googlename = self.RepositoryName()
 
741
    project, rest = os.path.split(googlename)
 
742
    return (project,) + os.path.splitext(rest)
 
743
 
 
744
  def BaseName(self):
 
745
    """File base name - text after the final slash, before the final period."""
 
746
    return self.Split()[1]
 
747
 
 
748
  def Extension(self):
 
749
    """File extension - text following the final period."""
 
750
    return self.Split()[2]
 
751
 
 
752
  def NoExtension(self):
 
753
    """File has no source file extension."""
 
754
    return '/'.join(self.Split()[0:2])
 
755
 
 
756
  def IsSource(self):
 
757
    """File has a source file extension."""
 
758
    return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
 
759
 
 
760
 
 
761
def _ShouldPrintError(category, confidence, linenum):
 
762
  """Returns true iff confidence >= verbose, category passes
 
763
  filter and is not NOLINT-suppressed."""
 
764
 
 
765
  # There are three ways we might decide not to print an error message:
 
766
  # a "NOLINT(category)" comment appears in the source,
 
767
  # the verbosity level isn't high enough, or the filters filter it out.
 
768
  if IsErrorSuppressedByNolint(category, linenum):
 
769
    return False
 
770
  if confidence < _cpplint_state.verbose_level:
 
771
    return False
 
772
 
 
773
  is_filtered = False
 
774
  for one_filter in _Filters():
 
775
    if one_filter.startswith('-'):
 
776
      if category.startswith(one_filter[1:]):
 
777
        is_filtered = True
 
778
    elif one_filter.startswith('+'):
 
779
      if category.startswith(one_filter[1:]):
 
780
        is_filtered = False
 
781
    else:
 
782
      assert False  # should have been checked for in SetFilter.
 
783
  if is_filtered:
 
784
    return False
 
785
 
 
786
  return True
 
787
 
 
788
 
 
789
def Error(filename, linenum, category, confidence, message):
 
790
  """Logs the fact we've found a lint error.
 
791
 
 
792
  We log where the error was found, and also our confidence in the error,
 
793
  that is, how certain we are this is a legitimate style regression, and
 
794
  not a misidentification or a use that's sometimes justified.
 
795
 
 
796
  False positives can be suppressed by the use of
 
797
  "cpplint(category)"  comments on the offending line.  These are
 
798
  parsed into _error_suppressions.
 
799
 
 
800
  Args:
 
801
    filename: The name of the file containing the error.
 
802
    linenum: The number of the line containing the error.
 
803
    category: A string used to describe the "category" this bug
 
804
      falls under: "whitespace", say, or "runtime".  Categories
 
805
      may have a hierarchy separated by slashes: "whitespace/indent".
 
806
    confidence: A number from 1-5 representing a confidence score for
 
807
      the error, with 5 meaning that we are certain of the problem,
 
808
      and 1 meaning that it could be a legitimate construct.
 
809
    message: The error message.
 
810
  """
 
811
  if _ShouldPrintError(category, confidence, linenum):
 
812
    _cpplint_state.IncrementErrorCount(category)
 
813
    if _cpplint_state.output_format == 'vs7':
 
814
      sys.stderr.write('%s(%s):  %s  [%s] [%d]\n' % (
 
815
          filename, linenum, message, category, confidence))
 
816
    else:
 
817
      sys.stderr.write('%s:%s:  %s  [%s] [%d]\n' % (
 
818
          filename, linenum, message, category, confidence))
 
819
 
 
820
 
 
821
# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard.
 
822
_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
 
823
    r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
 
824
# Matches strings.  Escape codes should already be removed by ESCAPES.
 
825
_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
 
826
# Matches characters.  Escape codes should already be removed by ESCAPES.
 
827
_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
 
828
# Matches multi-line C++ comments.
 
829
# This RE is a little bit more complicated than one might expect, because we
 
830
# have to take care of space removals tools so we can handle comments inside
 
831
# statements better.
 
832
# The current rule is: We only clear spaces from both sides when we're at the
 
833
# end of the line. Otherwise, we try to remove spaces from the right side,
 
834
# if this doesn't work we try on left side but only if there's a non-character
 
835
# on the right.
 
836
_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
 
837
    r"""(\s*/\*.*\*/\s*$|
 
838
            /\*.*\*/\s+|
 
839
         \s+/\*.*\*/(?=\W)|
 
840
            /\*.*\*/)""", re.VERBOSE)
 
841
 
 
842
 
 
843
def IsCppString(line):
 
844
  """Does line terminate so, that the next symbol is in string constant.
 
845
 
 
846
  This function does not consider single-line nor multi-line comments.
 
847
 
 
848
  Args:
 
849
    line: is a partial line of code starting from the 0..n.
 
850
 
 
851
  Returns:
 
852
    True, if next character appended to 'line' is inside a
 
853
    string constant.
 
854
  """
 
855
 
 
856
  line = line.replace(r'\\', 'XX')  # after this, \\" does not match to \"
 
857
  return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
 
858
 
 
859
 
 
860
def FindNextMultiLineCommentStart(lines, lineix):
 
861
  """Find the beginning marker for a multiline comment."""
 
862
  while lineix < len(lines):
 
863
    if lines[lineix].strip().startswith('/*'):
 
864
      # Only return this marker if the comment goes beyond this line
 
865
      if lines[lineix].strip().find('*/', 2) < 0:
 
866
        return lineix
 
867
    lineix += 1
 
868
  return len(lines)
 
869
 
 
870
 
 
871
def FindNextMultiLineCommentEnd(lines, lineix):
 
872
  """We are inside a comment, find the end marker."""
 
873
  while lineix < len(lines):
 
874
    if lines[lineix].strip().endswith('*/'):
 
875
      return lineix
 
876
    lineix += 1
 
877
  return len(lines)
 
878
 
 
879
 
 
880
def RemoveMultiLineCommentsFromRange(lines, begin, end):
 
881
  """Clears a range of lines for multi-line comments."""
 
882
  # Having // dummy comments makes the lines non-empty, so we will not get
 
883
  # unnecessary blank line warnings later in the code.
 
884
  for i in range(begin, end):
 
885
    lines[i] = '// dummy'
 
886
 
 
887
 
 
888
def RemoveMultiLineComments(filename, lines, error):
 
889
  """Removes multiline (c-style) comments from lines."""
 
890
  lineix = 0
 
891
  while lineix < len(lines):
 
892
    lineix_begin = FindNextMultiLineCommentStart(lines, lineix)
 
893
    if lineix_begin >= len(lines):
 
894
      return
 
895
    lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin)
 
896
    if lineix_end >= len(lines):
 
897
      error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
 
898
            'Could not find end of multi-line comment')
 
899
      return
 
900
    RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
 
901
    lineix = lineix_end + 1
 
902
 
 
903
 
 
904
def CleanseComments(line):
 
905
  """Removes //-comments and single-line C-style /* */ comments.
 
906
 
 
907
  Args:
 
908
    line: A line of C++ source.
 
909
 
 
910
  Returns:
 
911
    The line with single-line comments removed.
 
912
  """
 
913
  commentpos = line.find('//')
 
914
  if commentpos != -1 and not IsCppString(line[:commentpos]):
 
915
    line = line[:commentpos]
 
916
  # get rid of /* ... */
 
917
  return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
 
918
 
 
919
 
 
920
class CleansedLines(object):
 
921
  """Holds 3 copies of all lines with different preprocessing applied to them.
 
922
 
 
923
  1) elided member contains lines without strings and comments,
 
924
  2) lines member contains lines without comments, and
 
925
  3) raw member contains all the lines without processing.
 
926
  All these three members are of <type 'list'>, and of the same length.
 
927
  """
 
928
 
 
929
  def __init__(self, lines):
 
930
    self.elided = []
 
931
    self.lines = []
 
932
    self.raw_lines = lines
 
933
    self.num_lines = len(lines)
 
934
    for linenum in range(len(lines)):
 
935
      self.lines.append(CleanseComments(lines[linenum]))
 
936
      elided = self._CollapseStrings(lines[linenum])
 
937
      self.elided.append(CleanseComments(elided))
 
938
 
 
939
  def NumLines(self):
 
940
    """Returns the number of lines represented."""
 
941
    return self.num_lines
 
942
 
 
943
  @staticmethod
 
944
  def _CollapseStrings(elided):
 
945
    """Collapses strings and chars on a line to simple "" or '' blocks.
 
946
 
 
947
    We nix strings first so we're not fooled by text like '"http://"'
 
948
 
 
949
    Args:
 
950
      elided: The line being processed.
 
951
 
 
952
    Returns:
 
953
      The line with collapsed strings.
 
954
    """
 
955
    if not _RE_PATTERN_INCLUDE.match(elided):
 
956
      # Remove escaped characters first to make quote/single quote collapsing
 
957
      # basic.  Things that look like escaped characters shouldn't occur
 
958
      # outside of strings and chars.
 
959
      elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
 
960
      elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
 
961
      elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
 
962
    return elided
 
963
 
 
964
 
 
965
def CloseExpression(clean_lines, linenum, pos):
 
966
  """If input points to ( or { or [, finds the position that closes it.
 
967
 
 
968
  If lines[linenum][pos] points to a '(' or '{' or '[', finds the the
 
969
  linenum/pos that correspond to the closing of the expression.
 
970
 
 
971
  Args:
 
972
    clean_lines: A CleansedLines instance containing the file.
 
973
    linenum: The number of the line to check.
 
974
    pos: A position on the line.
 
975
 
 
976
  Returns:
 
977
    A tuple (line, linenum, pos) pointer *past* the closing brace, or
 
978
    (line, len(lines), -1) if we never find a close.  Note we ignore
 
979
    strings and comments when matching; and the line we return is the
 
980
    'cleansed' line at linenum.
 
981
  """
 
982
 
 
983
  line = clean_lines.elided[linenum]
 
984
  startchar = line[pos]
 
985
  if startchar not in '({[':
 
986
    return (line, clean_lines.NumLines(), -1)
 
987
  if startchar == '(': endchar = ')'
 
988
  if startchar == '[': endchar = ']'
 
989
  if startchar == '{': endchar = '}'
 
990
 
 
991
  num_open = line.count(startchar) - line.count(endchar)
 
992
  while linenum < clean_lines.NumLines() and num_open > 0:
 
993
    linenum += 1
 
994
    line = clean_lines.elided[linenum]
 
995
    num_open += line.count(startchar) - line.count(endchar)
 
996
  # OK, now find the endchar that actually got us back to even
 
997
  endpos = len(line)
 
998
  while num_open >= 0:
 
999
    endpos = line.rfind(')', 0, endpos)
 
1000
    num_open -= 1                 # chopped off another )
 
1001
  return (line, linenum, endpos + 1)
 
1002
 
 
1003
 
 
1004
def CheckForCopyright(filename, lines, error):
 
1005
  """Logs an error if no Copyright message appears at the top of the file."""
 
1006
 
 
1007
  # We'll say it should occur by line 10. Don't forget there's a
 
1008
  # dummy line at the front.
 
1009
  for line in xrange(1, min(len(lines), 11)):
 
1010
    if re.search(r'Copyright', lines[line], re.I): break
 
1011
  else:                       # means no copyright line was found
 
1012
    error(filename, 0, 'legal/copyright', 5,
 
1013
          'No copyright message found.  '
 
1014
          'You should have a line: "Copyright [year] <Copyright Owner>"')
 
1015
 
 
1016
 
 
1017
def GetHeaderGuardCPPVariable(filename):
 
1018
  """Returns the CPP variable that should be used as a header guard.
 
1019
 
 
1020
  Args:
 
1021
    filename: The name of a C++ header file.
 
1022
 
 
1023
  Returns:
 
1024
    The CPP variable that should be used as a header guard in the
 
1025
    named file.
 
1026
 
 
1027
  """
 
1028
 
 
1029
  # Restores original filename in case that cpplint is invoked from Emacs's
 
1030
  # flymake.
 
1031
  filename = re.sub(r'_flymake\.h$', '.h', filename)
 
1032
 
 
1033
  fileinfo = FileInfo(filename)
 
1034
  return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_'
 
1035
 
 
1036
 
 
1037
def CheckForHeaderGuard(filename, lines, error):
 
1038
  """Checks that the file contains a header guard.
 
1039
 
 
1040
  Logs an error if no #ifndef header guard is present.  For other
 
1041
  headers, checks that the full pathname is used.
 
1042
 
 
1043
  Args:
 
1044
    filename: The name of the C++ header file.
 
1045
    lines: An array of strings, each representing a line of the file.
 
1046
    error: The function to call with any errors found.
 
1047
  """
 
1048
 
 
1049
  cppvar = GetHeaderGuardCPPVariable(filename)
 
1050
 
 
1051
  ifndef = None
 
1052
  ifndef_linenum = 0
 
1053
  define = None
 
1054
  endif = None
 
1055
  endif_linenum = 0
 
1056
  for linenum, line in enumerate(lines):
 
1057
    linesplit = line.split()
 
1058
    if len(linesplit) >= 2:
 
1059
      # find the first occurrence of #ifndef and #define, save arg
 
1060
      if not ifndef and linesplit[0] == '#ifndef':
 
1061
        # set ifndef to the header guard presented on the #ifndef line.
 
1062
        ifndef = linesplit[1]
 
1063
        ifndef_linenum = linenum
 
1064
      if not define and linesplit[0] == '#define':
 
1065
        define = linesplit[1]
 
1066
    # find the last occurrence of #endif, save entire line
 
1067
    if line.startswith('#endif'):
 
1068
      endif = line
 
1069
      endif_linenum = linenum
 
1070
 
 
1071
  if not ifndef or not define or ifndef != define:
 
1072
    error(filename, 0, 'build/header_guard', 5,
 
1073
          'No #ifndef header guard found, suggested CPP variable is: %s' %
 
1074
          cppvar)
 
1075
    return
 
1076
 
 
1077
  # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__
 
1078
  # for backward compatibility.
 
1079
  if ifndef != cppvar:
 
1080
    error_level = 0
 
1081
    if ifndef != cppvar + '_':
 
1082
      error_level = 5
 
1083
 
 
1084
    ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum,
 
1085
                            error)
 
1086
    error(filename, ifndef_linenum, 'build/header_guard', error_level,
 
1087
          '#ifndef header guard has wrong style, please use: %s' % cppvar)
 
1088
 
 
1089
  if endif != ('#endif  // %s' % cppvar):
 
1090
    error_level = 0
 
1091
    if endif != ('#endif  // %s' % (cppvar + '_')):
 
1092
      error_level = 5
 
1093
 
 
1094
    ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum,
 
1095
                            error)
 
1096
    error(filename, endif_linenum, 'build/header_guard', error_level,
 
1097
          '#endif line should be "#endif  // %s"' % cppvar)
 
1098
 
 
1099
 
 
1100
def CheckForUnicodeReplacementCharacters(filename, lines, error):
 
1101
  """Logs an error for each line containing Unicode replacement characters.
 
1102
 
 
1103
  These indicate that either the file contained invalid UTF-8 (likely)
 
1104
  or Unicode replacement characters (which it shouldn't).  Note that
 
1105
  it's possible for this to throw off line numbering if the invalid
 
1106
  UTF-8 occurred adjacent to a newline.
 
1107
 
 
1108
  Args:
 
1109
    filename: The name of the current file.
 
1110
    lines: An array of strings, each representing a line of the file.
 
1111
    error: The function to call with any errors found.
 
1112
  """
 
1113
  for linenum, line in enumerate(lines):
 
1114
    if u'\ufffd' in line:
 
1115
      error(filename, linenum, 'readability/utf8', 5,
 
1116
            'Line contains invalid UTF-8 (or Unicode replacement character).')
 
1117
 
 
1118
 
 
1119
def CheckForNewlineAtEOF(filename, lines, error):
 
1120
  """Logs an error if there is no newline char at the end of the file.
 
1121
 
 
1122
  Args:
 
1123
    filename: The name of the current file.
 
1124
    lines: An array of strings, each representing a line of the file.
 
1125
    error: The function to call with any errors found.
 
1126
  """
 
1127
 
 
1128
  # The array lines() was created by adding two newlines to the
 
1129
  # original file (go figure), then splitting on \n.
 
1130
  # To verify that the file ends in \n, we just have to make sure the
 
1131
  # last-but-two element of lines() exists and is empty.
 
1132
  if len(lines) < 3 or lines[-2]:
 
1133
    error(filename, len(lines) - 2, 'whitespace/ending_newline', 5,
 
1134
          'Could not find a newline character at the end of the file.')
 
1135
 
 
1136
 
 
1137
def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error):
 
1138
  """Logs an error if we see /* ... */ or "..." that extend past one line.
 
1139
 
 
1140
  /* ... */ comments are legit inside macros, for one line.
 
1141
  Otherwise, we prefer // comments, so it's ok to warn about the
 
1142
  other.  Likewise, it's ok for strings to extend across multiple
 
1143
  lines, as long as a line continuation character (backslash)
 
1144
  terminates each line. Although not currently prohibited by the C++
 
1145
  style guide, it's ugly and unnecessary. We don't do well with either
 
1146
  in this lint program, so we warn about both.
 
1147
 
 
1148
  Args:
 
1149
    filename: The name of the current file.
 
1150
    clean_lines: A CleansedLines instance containing the file.
 
1151
    linenum: The number of the line to check.
 
1152
    error: The function to call with any errors found.
 
1153
  """
 
1154
  line = clean_lines.elided[linenum]
 
1155
 
 
1156
  # Remove all \\ (escaped backslashes) from the line. They are OK, and the
 
1157
  # second (escaped) slash may trigger later \" detection erroneously.
 
1158
  line = line.replace('\\\\', '')
 
1159
 
 
1160
  if line.count('/*') > line.count('*/'):
 
1161
    error(filename, linenum, 'readability/multiline_comment', 5,
 
1162
          'Complex multi-line /*...*/-style comment found. '
 
1163
          'Lint may give bogus warnings.  '
 
1164
          'Consider replacing these with //-style comments, '
 
1165
          'with #if 0...#endif, '
 
1166
          'or with more clearly structured multi-line comments.')
 
1167
 
 
1168
  if (line.count('"') - line.count('\\"')) % 2:
 
1169
    error(filename, linenum, 'readability/multiline_string', 5,
 
1170
          'Multi-line string ("...") found.  This lint script doesn\'t '
 
1171
          'do well with such strings, and may give bogus warnings.  They\'re '
 
1172
          'ugly and unnecessary, and you should use concatenation instead".')
 
1173
 
 
1174
 
 
1175
threading_list = (
 
1176
    ('asctime(', 'asctime_r('),
 
1177
    ('ctime(', 'ctime_r('),
 
1178
    ('getgrgid(', 'getgrgid_r('),
 
1179
    ('getgrnam(', 'getgrnam_r('),
 
1180
    ('getlogin(', 'getlogin_r('),
 
1181
    ('getpwnam(', 'getpwnam_r('),
 
1182
    ('getpwuid(', 'getpwuid_r('),
 
1183
    ('gmtime(', 'gmtime_r('),
 
1184
    ('localtime(', 'localtime_r('),
 
1185
    ('rand(', 'rand_r('),
 
1186
    ('readdir(', 'readdir_r('),
 
1187
    ('strtok(', 'strtok_r('),
 
1188
    ('ttyname(', 'ttyname_r('),
 
1189
    )
 
1190
 
 
1191
 
 
1192
def CheckPosixThreading(filename, clean_lines, linenum, error):
 
1193
  """Checks for calls to thread-unsafe functions.
 
1194
 
 
1195
  Much code has been originally written without consideration of
 
1196
  multi-threading. Also, engineers are relying on their old experience;
 
1197
  they have learned posix before threading extensions were added. These
 
1198
  tests guide the engineers to use thread-safe functions (when using
 
1199
  posix directly).
 
1200
 
 
1201
  Args:
 
1202
    filename: The name of the current file.
 
1203
    clean_lines: A CleansedLines instance containing the file.
 
1204
    linenum: The number of the line to check.
 
1205
    error: The function to call with any errors found.
 
1206
  """
 
1207
  line = clean_lines.elided[linenum]
 
1208
  for single_thread_function, multithread_safe_function in threading_list:
 
1209
    ix = line.find(single_thread_function)
 
1210
    # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
 
1211
    if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and
 
1212
                                line[ix - 1] not in ('_', '.', '>'))):
 
1213
      error(filename, linenum, 'runtime/threadsafe_fn', 2,
 
1214
            'Consider using ' + multithread_safe_function +
 
1215
            '...) instead of ' + single_thread_function +
 
1216
            '...) for improved thread safety.')
 
1217
 
 
1218
 
 
1219
# Matches invalid increment: *count++, which moves pointer instead of
 
1220
# incrementing a value.
 
1221
_RE_PATTERN_INVALID_INCREMENT = re.compile(
 
1222
    r'^\s*\*\w+(\+\+|--);')
 
1223
 
 
1224
 
 
1225
def CheckInvalidIncrement(filename, clean_lines, linenum, error):
 
1226
  """Checks for invalid increment *count++.
 
1227
 
 
1228
  For example following function:
 
1229
  void increment_counter(int* count) {
 
1230
    *count++;
 
1231
  }
 
1232
  is invalid, because it effectively does count++, moving pointer, and should
 
1233
  be replaced with ++*count, (*count)++ or *count += 1.
 
1234
 
 
1235
  Args:
 
1236
    filename: The name of the current file.
 
1237
    clean_lines: A CleansedLines instance containing the file.
 
1238
    linenum: The number of the line to check.
 
1239
    error: The function to call with any errors found.
 
1240
  """
 
1241
  line = clean_lines.elided[linenum]
 
1242
  if _RE_PATTERN_INVALID_INCREMENT.match(line):
 
1243
    error(filename, linenum, 'runtime/invalid_increment', 5,
 
1244
          'Changing pointer instead of value (or unused value of operator*).')
 
1245
 
 
1246
 
 
1247
class _ClassInfo(object):
 
1248
  """Stores information about a class."""
 
1249
 
 
1250
  def __init__(self, name, linenum):
 
1251
    self.name = name
 
1252
    self.linenum = linenum
 
1253
    self.seen_open_brace = False
 
1254
    self.is_derived = False
 
1255
    self.virtual_method_linenumber = None
 
1256
    self.has_virtual_destructor = False
 
1257
    self.brace_depth = 0
 
1258
 
 
1259
 
 
1260
class _ClassState(object):
 
1261
  """Holds the current state of the parse relating to class declarations.
 
1262
 
 
1263
  It maintains a stack of _ClassInfos representing the parser's guess
 
1264
  as to the current nesting of class declarations. The innermost class
 
1265
  is at the top (back) of the stack. Typically, the stack will either
 
1266
  be empty or have exactly one entry.
 
1267
  """
 
1268
 
 
1269
  def __init__(self):
 
1270
    self.classinfo_stack = []
 
1271
 
 
1272
  def CheckFinished(self, filename, error):
 
1273
    """Checks that all classes have been completely parsed.
 
1274
 
 
1275
    Call this when all lines in a file have been processed.
 
1276
    Args:
 
1277
      filename: The name of the current file.
 
1278
      error: The function to call with any errors found.
 
1279
    """
 
1280
    if self.classinfo_stack:
 
1281
      # Note: This test can result in false positives if #ifdef constructs
 
1282
      # get in the way of brace matching. See the testBuildClass test in
 
1283
      # cpplint_unittest.py for an example of this.
 
1284
      error(filename, self.classinfo_stack[0].linenum, 'build/class', 5,
 
1285
            'Failed to find complete declaration of class %s' %
 
1286
            self.classinfo_stack[0].name)
 
1287
 
 
1288
 
 
1289
def CheckForNonStandardConstructs(filename, clean_lines, linenum,
 
1290
                                  class_state, error):
 
1291
  """Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
 
1292
 
 
1293
  Complain about several constructs which gcc-2 accepts, but which are
 
1294
  not standard C++.  Warning about these in lint is one way to ease the
 
1295
  transition to new compilers.
 
1296
  - put storage class first (e.g. "static const" instead of "const static").
 
1297
  - "%lld" instead of %qd" in printf-type functions.
 
1298
  - "%1$d" is non-standard in printf-type functions.
 
1299
  - "\%" is an undefined character escape sequence.
 
1300
  - text after #endif is not allowed.
 
1301
  - invalid inner-style forward declaration.
 
1302
  - >? and <? operators, and their >?= and <?= cousins.
 
1303
  - classes with virtual methods need virtual destructors (compiler warning
 
1304
    available, but not turned on yet.)
 
1305
 
 
1306
  Additionally, check for constructor/destructor style violations and reference
 
1307
  members, as it is very convenient to do so while checking for
 
1308
  gcc-2 compliance.
 
1309
 
 
1310
  Args:
 
1311
    filename: The name of the current file.
 
1312
    clean_lines: A CleansedLines instance containing the file.
 
1313
    linenum: The number of the line to check.
 
1314
    class_state: A _ClassState instance which maintains information about
 
1315
                 the current stack of nested class declarations being parsed.
 
1316
    error: A callable to which errors are reported, which takes 4 arguments:
 
1317
           filename, line number, error level, and message
 
1318
  """
 
1319
 
 
1320
  # Remove comments from the line, but leave in strings for now.
 
1321
  line = clean_lines.lines[linenum]
 
1322
 
 
1323
  if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
 
1324
    error(filename, linenum, 'runtime/printf_format', 3,
 
1325
          '%q in format strings is deprecated.  Use %ll instead.')
 
1326
 
 
1327
  if Search(r'printf\s*\(.*".*%\d+\$', line):
 
1328
    error(filename, linenum, 'runtime/printf_format', 2,
 
1329
          '%N$ formats are unconventional.  Try rewriting to avoid them.')
 
1330
 
 
1331
  # Remove escaped backslashes before looking for undefined escapes.
 
1332
  line = line.replace('\\\\', '')
 
1333
 
 
1334
  if Search(r'("|\').*\\(%|\[|\(|{)', line):
 
1335
    error(filename, linenum, 'build/printf_format', 3,
 
1336
          '%, [, (, and { are undefined character escapes.  Unescape them.')
 
1337
 
 
1338
  # For the rest, work with both comments and strings removed.
 
1339
  line = clean_lines.elided[linenum]
 
1340
 
 
1341
  if Search(r'\b(const|volatile|void|char|short|int|long'
 
1342
            r'|float|double|signed|unsigned'
 
1343
            r'|schar|u?int8|u?int16|u?int32|u?int64)'
 
1344
            r'\s+(auto|register|static|extern|typedef)\b',
 
1345
            line):
 
1346
    error(filename, linenum, 'build/storage_class', 5,
 
1347
          'Storage class (static, extern, typedef, etc) should be first.')
 
1348
 
 
1349
  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
 
1350
    error(filename, linenum, 'build/endif_comment', 5,
 
1351
          'Uncommented text after #endif is non-standard.  Use a comment.')
 
1352
 
 
1353
  if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
 
1354
    error(filename, linenum, 'build/forward_decl', 5,
 
1355
          'Inner-style forward declarations are invalid.  Remove this line.')
 
1356
 
 
1357
  if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
 
1358
            line):
 
1359
    error(filename, linenum, 'build/deprecated', 3,
 
1360
          '>? and <? (max and min) operators are non-standard and deprecated.')
 
1361
 
 
1362
  if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
 
1363
    # TODO(unknown): Could it be expanded safely to arbitrary references,
 
1364
    # without triggering too many false positives? The first
 
1365
    # attempt triggered 5 warnings for mostly benign code in the regtest, hence
 
1366
    # the restriction.
 
1367
    # Here's the original regexp, for the reference:
 
1368
    # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
 
1369
    # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
 
1370
    error(filename, linenum, 'runtime/member_string_references', 2,
 
1371
          'const string& members are dangerous. It is much better to use '
 
1372
          'alternatives, such as pointers or simple constants.')
 
1373
 
 
1374
  # Track class entry and exit, and attempt to find cases within the
 
1375
  # class declaration that don't meet the C++ style
 
1376
  # guidelines. Tracking is very dependent on the code matching Google
 
1377
  # style guidelines, but it seems to perform well enough in testing
 
1378
  # to be a worthwhile addition to the checks.
 
1379
  classinfo_stack = class_state.classinfo_stack
 
1380
  # Look for a class declaration
 
1381
  class_decl_match = Match(
 
1382
      r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line)
 
1383
  if class_decl_match:
 
1384
    classinfo_stack.append(_ClassInfo(class_decl_match.group(3), linenum))
 
1385
 
 
1386
  # Everything else in this function uses the top of the stack if it's
 
1387
  # not empty.
 
1388
  if not classinfo_stack:
 
1389
    return
 
1390
 
 
1391
  classinfo = classinfo_stack[-1]
 
1392
 
 
1393
  # If the opening brace hasn't been seen look for it and also
 
1394
  # parent class declarations.
 
1395
  if not classinfo.seen_open_brace:
 
1396
    # If the line has a ';' in it, assume it's a forward declaration or
 
1397
    # a single-line class declaration, which we won't process.
 
1398
    if line.find(';') != -1:
 
1399
      classinfo_stack.pop()
 
1400
      return
 
1401
    classinfo.seen_open_brace = (line.find('{') != -1)
 
1402
    # Look for a bare ':'
 
1403
    if Search('(^|[^:]):($|[^:])', line):
 
1404
      classinfo.is_derived = True
 
1405
    if not classinfo.seen_open_brace:
 
1406
      return  # Everything else in this function is for after open brace
 
1407
 
 
1408
  # The class may have been declared with namespace or classname qualifiers.
 
1409
  # The constructor and destructor will not have those qualifiers.
 
1410
  base_classname = classinfo.name.split('::')[-1]
 
1411
 
 
1412
  # Look for single-argument constructors that aren't marked explicit.
 
1413
  # Technically a valid construct, but against style.
 
1414
  args = Match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)'
 
1415
               % re.escape(base_classname),
 
1416
               line)
 
1417
  if (args and
 
1418
      args.group(1) != 'void' and
 
1419
      not Match(r'(const\s+)?%s\s*&' % re.escape(base_classname),
 
1420
                args.group(1).strip())):
 
1421
    error(filename, linenum, 'runtime/explicit', 5,
 
1422
          'Single-argument constructors should be marked explicit.')
 
1423
 
 
1424
  # Look for methods declared virtual.
 
1425
  if Search(r'\bvirtual\b', line):
 
1426
    classinfo.virtual_method_linenumber = linenum
 
1427
    # Only look for a destructor declaration on the same line. It would
 
1428
    # be extremely unlikely for the destructor declaration to occupy
 
1429
    # more than one line.
 
1430
    if Search(r'~%s\s*\(' % base_classname, line):
 
1431
      classinfo.has_virtual_destructor = True
 
1432
 
 
1433
  # Look for class end.
 
1434
  brace_depth = classinfo.brace_depth
 
1435
  brace_depth = brace_depth + line.count('{') - line.count('}')
 
1436
  if brace_depth <= 0:
 
1437
    classinfo = classinfo_stack.pop()
 
1438
    # Try to detect missing virtual destructor declarations.
 
1439
    # For now, only warn if a non-derived class with virtual methods lacks
 
1440
    # a virtual destructor. This is to make it less likely that people will
 
1441
    # declare derived virtual destructors without declaring the base
 
1442
    # destructor virtual.
 
1443
    if ((classinfo.virtual_method_linenumber is not None) and
 
1444
        (not classinfo.has_virtual_destructor) and
 
1445
        (not classinfo.is_derived)):  # Only warn for base classes
 
1446
      error(filename, classinfo.linenum, 'runtime/virtual', 4,
 
1447
            'The class %s probably needs a virtual destructor due to '
 
1448
            'having virtual method(s), one declared at line %d.'
 
1449
            % (classinfo.name, classinfo.virtual_method_linenumber))
 
1450
  else:
 
1451
    classinfo.brace_depth = brace_depth
 
1452
 
 
1453
 
 
1454
def CheckSpacingForFunctionCall(filename, line, linenum, error):
 
1455
  """Checks for the correctness of various spacing around function calls.
 
1456
 
 
1457
  Args:
 
1458
    filename: The name of the current file.
 
1459
    line: The text of the line to check.
 
1460
    linenum: The number of the line to check.
 
1461
    error: The function to call with any errors found.
 
1462
  """
 
1463
 
 
1464
  # Since function calls often occur inside if/for/while/switch
 
1465
  # expressions - which have their own, more liberal conventions - we
 
1466
  # first see if we should be looking inside such an expression for a
 
1467
  # function call, to which we can apply more strict standards.
 
1468
  fncall = line    # if there's no control flow construct, look at whole line
 
1469
  for pattern in (r'\bif\s*\((.*)\)\s*{',
 
1470
                  r'\bfor\s*\((.*)\)\s*{',
 
1471
                  r'\bwhile\s*\((.*)\)\s*[{;]',
 
1472
                  r'\bswitch\s*\((.*)\)\s*{'):
 
1473
    match = Search(pattern, line)
 
1474
    if match:
 
1475
      fncall = match.group(1)    # look inside the parens for function calls
 
1476
      break
 
1477
 
 
1478
  # Except in if/for/while/switch, there should never be space
 
1479
  # immediately inside parens (eg "f( 3, 4 )").  We make an exception
 
1480
  # for nested parens ( (a+b) + c ).  Likewise, there should never be
 
1481
  # a space before a ( when it's a function argument.  I assume it's a
 
1482
  # function argument when the char before the whitespace is legal in
 
1483
  # a function name (alnum + _) and we're not starting a macro. Also ignore
 
1484
  # pointers and references to arrays and functions coz they're too tricky:
 
1485
  # we use a very simple way to recognize these:
 
1486
  # " (something)(maybe-something)" or
 
1487
  # " (something)(maybe-something," or
 
1488
  # " (something)[something]"
 
1489
  # Note that we assume the contents of [] to be short enough that
 
1490
  # they'll never need to wrap.
 
1491
  if (  # Ignore control structures.
 
1492
      not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and
 
1493
      # Ignore pointers/references to functions.
 
1494
      not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
 
1495
      # Ignore pointers/references to arrays.
 
1496
      not Search(r' \([^)]+\)\[[^\]]+\]', fncall)):
 
1497
    if Search(r'\w\s*\(\s(?!\s*\\$)', fncall):      # a ( used for a fn call
 
1498
      error(filename, linenum, 'whitespace/parens', 4,
 
1499
            'Extra space after ( in function call')
 
1500
    elif Search(r'\(\s+(?!(\s*\\)|\()', fncall):
 
1501
      error(filename, linenum, 'whitespace/parens', 2,
 
1502
            'Extra space after (')
 
1503
    if (Search(r'\w\s+\(', fncall) and
 
1504
        not Search(r'#\s*define|typedef', fncall)):
 
1505
      error(filename, linenum, 'whitespace/parens', 4,
 
1506
            'Extra space before ( in function call')
 
1507
    # If the ) is followed only by a newline or a { + newline, assume it's
 
1508
    # part of a control statement (if/while/etc), and don't complain
 
1509
    if Search(r'[^)]\s+\)\s*[^{\s]', fncall):
 
1510
      error(filename, linenum, 'whitespace/parens', 2,
 
1511
            'Extra space before )')
 
1512
 
 
1513
 
 
1514
def IsBlankLine(line):
 
1515
  """Returns true if the given line is blank.
 
1516
 
 
1517
  We consider a line to be blank if the line is empty or consists of
 
1518
  only white spaces.
 
1519
 
 
1520
  Args:
 
1521
    line: A line of a string.
 
1522
 
 
1523
  Returns:
 
1524
    True, if the given line is blank.
 
1525
  """
 
1526
  return not line or line.isspace()
 
1527
 
 
1528
 
 
1529
def CheckForFunctionLengths(filename, clean_lines, linenum,
 
1530
                            function_state, error):
 
1531
  """Reports for long function bodies.
 
1532
 
 
1533
  For an overview why this is done, see:
 
1534
  http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
 
1535
 
 
1536
  Uses a simplistic algorithm assuming other style guidelines
 
1537
  (especially spacing) are followed.
 
1538
  Only checks unindented functions, so class members are unchecked.
 
1539
  Trivial bodies are unchecked, so constructors with huge initializer lists
 
1540
  may be missed.
 
1541
  Blank/comment lines are not counted so as to avoid encouraging the removal
 
1542
  of vertical space and commments just to get through a lint check.
 
1543
  NOLINT *on the last line of a function* disables this check.
 
1544
 
 
1545
  Args:
 
1546
    filename: The name of the current file.
 
1547
    clean_lines: A CleansedLines instance containing the file.
 
1548
    linenum: The number of the line to check.
 
1549
    function_state: Current function name and lines in body so far.
 
1550
    error: The function to call with any errors found.
 
1551
  """
 
1552
  lines = clean_lines.lines
 
1553
  line = lines[linenum]
 
1554
  raw = clean_lines.raw_lines
 
1555
  raw_line = raw[linenum]
 
1556
  joined_line = ''
 
1557
 
 
1558
  starting_func = False
 
1559
  regexp = r'(\w(\w|::|\*|\&|\s)*)\('  # decls * & space::name( ...
 
1560
  match_result = Match(regexp, line)
 
1561
  if match_result:
 
1562
    # If the name is all caps and underscores, figure it's a macro and
 
1563
    # ignore it, unless it's TEST or TEST_F.
 
1564
    function_name = match_result.group(1).split()[-1]
 
1565
    if function_name == 'TEST' or function_name == 'TEST_F' or (
 
1566
        not Match(r'[A-Z_]+$', function_name)):
 
1567
      starting_func = True
 
1568
 
 
1569
  if starting_func:
 
1570
    body_found = False
 
1571
    for start_linenum in xrange(linenum, clean_lines.NumLines()):
 
1572
      start_line = lines[start_linenum]
 
1573
      joined_line += ' ' + start_line.lstrip()
 
1574
      if Search(r'(;|})', start_line):  # Declarations and trivial functions
 
1575
        body_found = True
 
1576
        break                              # ... ignore
 
1577
      elif Search(r'{', start_line):
 
1578
        body_found = True
 
1579
        function = Search(r'((\w|:)*)\(', line).group(1)
 
1580
        if Match(r'TEST', function):    # Handle TEST... macros
 
1581
          parameter_regexp = Search(r'(\(.*\))', joined_line)
 
1582
          if parameter_regexp:             # Ignore bad syntax
 
1583
            function += parameter_regexp.group(1)
 
1584
        else:
 
1585
          function += '()'
 
1586
        function_state.Begin(function)
 
1587
        break
 
1588
    if not body_found:
 
1589
      # No body for the function (or evidence of a non-function) was found.
 
1590
      error(filename, linenum, 'readability/fn_size', 5,
 
1591
            'Lint failed to find start of function body.')
 
1592
  elif Match(r'^\}\s*$', line):  # function end
 
1593
    function_state.Check(error, filename, linenum)
 
1594
    function_state.End()
 
1595
  elif not Match(r'^\s*$', line):
 
1596
    function_state.Count()  # Count non-blank/non-comment lines.
 
1597
 
 
1598
 
 
1599
_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?')
 
1600
 
 
1601
 
 
1602
def CheckComment(comment, filename, linenum, error):
 
1603
  """Checks for common mistakes in TODO comments.
 
1604
 
 
1605
  Args:
 
1606
    comment: The text of the comment from the line in question.
 
1607
    filename: The name of the current file.
 
1608
    linenum: The number of the line to check.
 
1609
    error: The function to call with any errors found.
 
1610
  """
 
1611
  match = _RE_PATTERN_TODO.match(comment)
 
1612
  if match:
 
1613
    # One whitespace is correct; zero whitespace is handled elsewhere.
 
1614
    leading_whitespace = match.group(1)
 
1615
    if len(leading_whitespace) > 1:
 
1616
      error(filename, linenum, 'whitespace/todo', 2,
 
1617
            'Too many spaces before TODO')
 
1618
 
 
1619
    username = match.group(2)
 
1620
    if not username:
 
1621
      error(filename, linenum, 'readability/todo', 2,
 
1622
            'Missing username in TODO; it should look like '
 
1623
            '"// TODO(my_username): Stuff."')
 
1624
 
 
1625
    middle_whitespace = match.group(3)
 
1626
    # Comparisons made explicit for correctness -- pylint: disable-msg=C6403
 
1627
    if middle_whitespace != ' ' and middle_whitespace != '':
 
1628
      error(filename, linenum, 'whitespace/todo', 2,
 
1629
            'TODO(my_username) should be followed by a space')
 
1630
 
 
1631
 
 
1632
def CheckSpacing(filename, clean_lines, linenum, error):
 
1633
  """Checks for the correctness of various spacing issues in the code.
 
1634
 
 
1635
  Things we check for: spaces around operators, spaces after
 
1636
  if/for/while/switch, no spaces around parens in function calls, two
 
1637
  spaces between code and comment, don't start a block with a blank
 
1638
  line, don't end a function with a blank line, don't have too many
 
1639
  blank lines in a row.
 
1640
 
 
1641
  Args:
 
1642
    filename: The name of the current file.
 
1643
    clean_lines: A CleansedLines instance containing the file.
 
1644
    linenum: The number of the line to check.
 
1645
    error: The function to call with any errors found.
 
1646
  """
 
1647
 
 
1648
  raw = clean_lines.raw_lines
 
1649
  line = raw[linenum]
 
1650
 
 
1651
  # Before nixing comments, check if the line is blank for no good
 
1652
  # reason.  This includes the first line after a block is opened, and
 
1653
  # blank lines at the end of a function (ie, right before a line like '}'
 
1654
  if IsBlankLine(line):
 
1655
    elided = clean_lines.elided
 
1656
    prev_line = elided[linenum - 1]
 
1657
    prevbrace = prev_line.rfind('{')
 
1658
    # TODO(unknown): Don't complain if line before blank line, and line after,
 
1659
    #                both start with alnums and are indented the same amount.
 
1660
    #                This ignores whitespace at the start of a namespace block
 
1661
    #                because those are not usually indented.
 
1662
    if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1
 
1663
        and prev_line[:prevbrace].find('namespace') == -1):
 
1664
      # OK, we have a blank line at the start of a code block.  Before we
 
1665
      # complain, we check if it is an exception to the rule: The previous
 
1666
      # non-empty line has the paramters of a function header that are indented
 
1667
      # 4 spaces (because they did not fit in a 80 column line when placed on
 
1668
      # the same line as the function name).  We also check for the case where
 
1669
      # the previous line is indented 6 spaces, which may happen when the
 
1670
      # initializers of a constructor do not fit into a 80 column line.
 
1671
      exception = False
 
1672
      if Match(r' {6}\w', prev_line):  # Initializer list?
 
1673
        # We are looking for the opening column of initializer list, which
 
1674
        # should be indented 4 spaces to cause 6 space indentation afterwards.
 
1675
        search_position = linenum-2
 
1676
        while (search_position >= 0
 
1677
               and Match(r' {6}\w', elided[search_position])):
 
1678
          search_position -= 1
 
1679
        exception = (search_position >= 0
 
1680
                     and elided[search_position][:5] == '    :')
 
1681
      else:
 
1682
        # Search for the function arguments or an initializer list.  We use a
 
1683
        # simple heuristic here: If the line is indented 4 spaces; and we have a
 
1684
        # closing paren, without the opening paren, followed by an opening brace
 
1685
        # or colon (for initializer lists) we assume that it is the last line of
 
1686
        # a function header.  If we have a colon indented 4 spaces, it is an
 
1687
        # initializer list.
 
1688
        exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
 
1689
                           prev_line)
 
1690
                     or Match(r' {4}:', prev_line))
 
1691
 
 
1692
      if not exception:
 
1693
        error(filename, linenum, 'whitespace/blank_line', 2,
 
1694
              'Blank line at the start of a code block.  Is this needed?')
 
1695
    # This doesn't ignore whitespace at the end of a namespace block
 
1696
    # because that is too hard without pairing open/close braces;
 
1697
    # however, a special exception is made for namespace closing
 
1698
    # brackets which have a comment containing "namespace".
 
1699
    #
 
1700
    # Also, ignore blank lines at the end of a block in a long if-else
 
1701
    # chain, like this:
 
1702
    #   if (condition1) {
 
1703
    #     // Something followed by a blank line
 
1704
    #
 
1705
    #   } else if (condition2) {
 
1706
    #     // Something else
 
1707
    #   }
 
1708
    if linenum + 1 < clean_lines.NumLines():
 
1709
      next_line = raw[linenum + 1]
 
1710
      if (next_line
 
1711
          and Match(r'\s*}', next_line)
 
1712
          and next_line.find('namespace') == -1
 
1713
          and next_line.find('} else ') == -1):
 
1714
        error(filename, linenum, 'whitespace/blank_line', 3,
 
1715
              'Blank line at the end of a code block.  Is this needed?')
 
1716
 
 
1717
  # Next, we complain if there's a comment too near the text
 
1718
  commentpos = line.find('//')
 
1719
  if commentpos != -1:
 
1720
    # Check if the // may be in quotes.  If so, ignore it
 
1721
    # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
 
1722
    if (line.count('"', 0, commentpos) -
 
1723
        line.count('\\"', 0, commentpos)) % 2 == 0:   # not in quotes
 
1724
      # Allow one space for new scopes, two spaces otherwise:
 
1725
      if (not Match(r'^\s*{ //', line) and
 
1726
          ((commentpos >= 1 and
 
1727
            line[commentpos-1] not in string.whitespace) or
 
1728
           (commentpos >= 2 and
 
1729
            line[commentpos-2] not in string.whitespace))):
 
1730
        error(filename, linenum, 'whitespace/comments', 2,
 
1731
              'At least two spaces is best between code and comments')
 
1732
      # There should always be a space between the // and the comment
 
1733
      commentend = commentpos + 2
 
1734
      if commentend < len(line) and not line[commentend] == ' ':
 
1735
        # but some lines are exceptions -- e.g. if they're big
 
1736
        # comment delimiters like:
 
1737
        # //----------------------------------------------------------
 
1738
        # or they begin with multiple slashes followed by a space:
 
1739
        # //////// Header comment
 
1740
        match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
 
1741
                 Search(r'^/+ ', line[commentend:]))
 
1742
        if not match:
 
1743
          error(filename, linenum, 'whitespace/comments', 4,
 
1744
                'Should have a space between // and comment')
 
1745
      CheckComment(line[commentpos:], filename, linenum, error)
 
1746
 
 
1747
  line = clean_lines.elided[linenum]  # get rid of comments and strings
 
1748
 
 
1749
  # Don't try to do spacing checks for operator methods
 
1750
  line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line)
 
1751
 
 
1752
  # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
 
1753
  # Otherwise not.  Note we only check for non-spaces on *both* sides;
 
1754
  # sometimes people put non-spaces on one side when aligning ='s among
 
1755
  # many lines (not that this is behavior that I approve of...)
 
1756
  if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line):
 
1757
    error(filename, linenum, 'whitespace/operators', 4,
 
1758
          'Missing spaces around =')
 
1759
 
 
1760
  # It's ok not to have spaces around binary operators like + - * /, but if
 
1761
  # there's too little whitespace, we get concerned.  It's hard to tell,
 
1762
  # though, so we punt on this one for now.  TODO.
 
1763
 
 
1764
  # You should always have whitespace around binary operators.
 
1765
  # Alas, we can't test < or > because they're legitimately used sans spaces
 
1766
  # (a->b, vector<int> a).  The only time we can tell is a < with no >, and
 
1767
  # only if it's not template params list spilling into the next line.
 
1768
  match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line)
 
1769
  if not match:
 
1770
    # Note that while it seems that the '<[^<]*' term in the following
 
1771
    # regexp could be simplified to '<.*', which would indeed match
 
1772
    # the same class of strings, the [^<] means that searching for the
 
1773
    # regexp takes linear rather than quadratic time.
 
1774
    if not Search(r'<[^<]*,\s*$', line):  # template params spill
 
1775
      match = Search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line)
 
1776
  if match:
 
1777
    error(filename, linenum, 'whitespace/operators', 3,
 
1778
          'Missing spaces around %s' % match.group(1))
 
1779
  # We allow no-spaces around << and >> when used like this: 10<<20, but
 
1780
  # not otherwise (particularly, not when used as streams)
 
1781
  match = Search(r'[^0-9\s](<<|>>)[^0-9\s]', line)
 
1782
  if match:
 
1783
    error(filename, linenum, 'whitespace/operators', 3,
 
1784
          'Missing spaces around %s' % match.group(1))
 
1785
 
 
1786
  # There shouldn't be space around unary operators
 
1787
  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
 
1788
  if match:
 
1789
    error(filename, linenum, 'whitespace/operators', 4,
 
1790
          'Extra space for operator %s' % match.group(1))
 
1791
 
 
1792
  # A pet peeve of mine: no spaces after an if, while, switch, or for
 
1793
  match = Search(r' (if\(|for\(|while\(|switch\()', line)
 
1794
  if match:
 
1795
    error(filename, linenum, 'whitespace/parens', 5,
 
1796
          'Missing space before ( in %s' % match.group(1))
 
1797
 
 
1798
  # For if/for/while/switch, the left and right parens should be
 
1799
  # consistent about how many spaces are inside the parens, and
 
1800
  # there should either be zero or one spaces inside the parens.
 
1801
  # We don't want: "if ( foo)" or "if ( foo   )".
 
1802
  # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
 
1803
  match = Search(r'\b(if|for|while|switch)\s*'
 
1804
                 r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$',
 
1805
                 line)
 
1806
  if match:
 
1807
    if len(match.group(2)) != len(match.group(4)):
 
1808
      if not (match.group(3) == ';' and
 
1809
              len(match.group(2)) == 1 + len(match.group(4)) or
 
1810
              not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)):
 
1811
        error(filename, linenum, 'whitespace/parens', 5,
 
1812
              'Mismatching spaces inside () in %s' % match.group(1))
 
1813
    if not len(match.group(2)) in [0, 1]:
 
1814
      error(filename, linenum, 'whitespace/parens', 5,
 
1815
            'Should have zero or one spaces inside ( and ) in %s' %
 
1816
            match.group(1))
 
1817
 
 
1818
  # You should always have a space after a comma (either as fn arg or operator)
 
1819
  if Search(r',[^\s]', line):
 
1820
    error(filename, linenum, 'whitespace/comma', 3,
 
1821
          'Missing space after ,')
 
1822
 
 
1823
  # Next we will look for issues with function calls.
 
1824
  CheckSpacingForFunctionCall(filename, line, linenum, error)
 
1825
 
 
1826
  # Except after an opening paren, you should have spaces before your braces.
 
1827
  # And since you should never have braces at the beginning of a line, this is
 
1828
  # an easy test.
 
1829
  if Search(r'[^ (]{', line):
 
1830
    error(filename, linenum, 'whitespace/braces', 5,
 
1831
          'Missing space before {')
 
1832
 
 
1833
  # Make sure '} else {' has spaces.
 
1834
  if Search(r'}else', line):
 
1835
    error(filename, linenum, 'whitespace/braces', 5,
 
1836
          'Missing space before else')
 
1837
 
 
1838
  # You shouldn't have spaces before your brackets, except maybe after
 
1839
  # 'delete []' or 'new char * []'.
 
1840
  if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line):
 
1841
    error(filename, linenum, 'whitespace/braces', 5,
 
1842
          'Extra space before [')
 
1843
 
 
1844
  # You shouldn't have a space before a semicolon at the end of the line.
 
1845
  # There's a special case for "for" since the style guide allows space before
 
1846
  # the semicolon there.
 
1847
  if Search(r':\s*;\s*$', line):
 
1848
    error(filename, linenum, 'whitespace/semicolon', 5,
 
1849
          'Semicolon defining empty statement. Use { } instead.')
 
1850
  elif Search(r'^\s*;\s*$', line):
 
1851
    error(filename, linenum, 'whitespace/semicolon', 5,
 
1852
          'Line contains only semicolon. If this should be an empty statement, '
 
1853
          'use { } instead.')
 
1854
  elif (Search(r'\s+;\s*$', line) and
 
1855
        not Search(r'\bfor\b', line)):
 
1856
    error(filename, linenum, 'whitespace/semicolon', 5,
 
1857
          'Extra space before last semicolon. If this should be an empty '
 
1858
          'statement, use { } instead.')
 
1859
 
 
1860
 
 
1861
def GetPreviousNonBlankLine(clean_lines, linenum):
 
1862
  """Return the most recent non-blank line and its line number.
 
1863
 
 
1864
  Args:
 
1865
    clean_lines: A CleansedLines instance containing the file contents.
 
1866
    linenum: The number of the line to check.
 
1867
 
 
1868
  Returns:
 
1869
    A tuple with two elements.  The first element is the contents of the last
 
1870
    non-blank line before the current line, or the empty string if this is the
 
1871
    first non-blank line.  The second is the line number of that line, or -1
 
1872
    if this is the first non-blank line.
 
1873
  """
 
1874
 
 
1875
  prevlinenum = linenum - 1
 
1876
  while prevlinenum >= 0:
 
1877
    prevline = clean_lines.elided[prevlinenum]
 
1878
    if not IsBlankLine(prevline):     # if not a blank line...
 
1879
      return (prevline, prevlinenum)
 
1880
    prevlinenum -= 1
 
1881
  return ('', -1)
 
1882
 
 
1883
 
 
1884
def CheckBraces(filename, clean_lines, linenum, error):
 
1885
  """Looks for misplaced braces (e.g. at the end of line).
 
1886
 
 
1887
  Args:
 
1888
    filename: The name of the current file.
 
1889
    clean_lines: A CleansedLines instance containing the file.
 
1890
    linenum: The number of the line to check.
 
1891
    error: The function to call with any errors found.
 
1892
  """
 
1893
 
 
1894
  line = clean_lines.elided[linenum]        # get rid of comments and strings
 
1895
 
 
1896
  if Match(r'\s*{\s*$', line):
 
1897
    # We allow an open brace to start a line in the case where someone
 
1898
    # is using braces in a block to explicitly create a new scope,
 
1899
    # which is commonly used to control the lifetime of
 
1900
    # stack-allocated variables.  We don't detect this perfectly: we
 
1901
    # just don't complain if the last non-whitespace character on the
 
1902
    # previous non-blank line is ';', ':', '{', or '}'.
 
1903
    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
 
1904
    if not Search(r'[;:}{]\s*$', prevline):
 
1905
      error(filename, linenum, 'whitespace/braces', 4,
 
1906
            '{ should almost always be at the end of the previous line')
 
1907
 
 
1908
  # An else clause should be on the same line as the preceding closing brace.
 
1909
  if Match(r'\s*else\s*', line):
 
1910
    prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
 
1911
    if Match(r'\s*}\s*$', prevline):
 
1912
      error(filename, linenum, 'whitespace/newline', 4,
 
1913
            'An else should appear on the same line as the preceding }')
 
1914
 
 
1915
  # If braces come on one side of an else, they should be on both.
 
1916
  # However, we have to worry about "else if" that spans multiple lines!
 
1917
  if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line):
 
1918
    if Search(r'}\s*else if([^{]*)$', line):       # could be multi-line if
 
1919
      # find the ( after the if
 
1920
      pos = line.find('else if')
 
1921
      pos = line.find('(', pos)
 
1922
      if pos > 0:
 
1923
        (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos)
 
1924
        if endline[endpos:].find('{') == -1:    # must be brace after if
 
1925
          error(filename, linenum, 'readability/braces', 5,
 
1926
                'If an else has a brace on one side, it should have it on both')
 
1927
    else:            # common case: else not followed by a multi-line if
 
1928
      error(filename, linenum, 'readability/braces', 5,
 
1929
            'If an else has a brace on one side, it should have it on both')
 
1930
 
 
1931
  # Likewise, an else should never have the else clause on the same line
 
1932
  if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line):
 
1933
    error(filename, linenum, 'whitespace/newline', 4,
 
1934
          'Else clause should never be on same line as else (use 2 lines)')
 
1935
 
 
1936
  # In the same way, a do/while should never be on one line
 
1937
  if Match(r'\s*do [^\s{]', line):
 
1938
    error(filename, linenum, 'whitespace/newline', 4,
 
1939
          'do/while clauses should not be on a single line')
 
1940
 
 
1941
  # Braces shouldn't be followed by a ; unless they're defining a struct
 
1942
  # or initializing an array.
 
1943
  # We can't tell in general, but we can for some common cases.
 
1944
  prevlinenum = linenum
 
1945
  while True:
 
1946
    (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum)
 
1947
    if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'):
 
1948
      line = prevline + line
 
1949
    else:
 
1950
      break
 
1951
  if (Search(r'{.*}\s*;', line) and
 
1952
      line.count('{') == line.count('}') and
 
1953
      not Search(r'struct|class|enum|\s*=\s*{', line)):
 
1954
    error(filename, linenum, 'readability/braces', 4,
 
1955
          "You don't need a ; after a }")
 
1956
 
 
1957
 
 
1958
def ReplaceableCheck(operator, macro, line):
 
1959
  """Determine whether a basic CHECK can be replaced with a more specific one.
 
1960
 
 
1961
  For example suggest using CHECK_EQ instead of CHECK(a == b) and
 
1962
  similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE.
 
1963
 
 
1964
  Args:
 
1965
    operator: The C++ operator used in the CHECK.
 
1966
    macro: The CHECK or EXPECT macro being called.
 
1967
    line: The current source line.
 
1968
 
 
1969
  Returns:
 
1970
    True if the CHECK can be replaced with a more specific one.
 
1971
  """
 
1972
 
 
1973
  # This matches decimal and hex integers, strings, and chars (in that order).
 
1974
  match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')'
 
1975
 
 
1976
  # Expression to match two sides of the operator with something that
 
1977
  # looks like a literal, since CHECK(x == iterator) won't compile.
 
1978
  # This means we can't catch all the cases where a more specific
 
1979
  # CHECK is possible, but it's less annoying than dealing with
 
1980
  # extraneous warnings.
 
1981
  match_this = (r'\s*' + macro + r'\((\s*' +
 
1982
                match_constant + r'\s*' + operator + r'[^<>].*|'
 
1983
                r'.*[^<>]' + operator + r'\s*' + match_constant +
 
1984
                r'\s*\))')
 
1985
 
 
1986
  # Don't complain about CHECK(x == NULL) or similar because
 
1987
  # CHECK_EQ(x, NULL) won't compile (requires a cast).
 
1988
  # Also, don't complain about more complex boolean expressions
 
1989
  # involving && or || such as CHECK(a == b || c == d).
 
1990
  return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line)
 
1991
 
 
1992
 
 
1993
def CheckCheck(filename, clean_lines, linenum, error):
 
1994
  """Checks the use of CHECK and EXPECT macros.
 
1995
 
 
1996
  Args:
 
1997
    filename: The name of the current file.
 
1998
    clean_lines: A CleansedLines instance containing the file.
 
1999
    linenum: The number of the line to check.
 
2000
    error: The function to call with any errors found.
 
2001
  """
 
2002
 
 
2003
  # Decide the set of replacement macros that should be suggested
 
2004
  raw_lines = clean_lines.raw_lines
 
2005
  current_macro = ''
 
2006
  for macro in _CHECK_MACROS:
 
2007
    if raw_lines[linenum].find(macro) >= 0:
 
2008
      current_macro = macro
 
2009
      break
 
2010
  if not current_macro:
 
2011
    # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT'
 
2012
    return
 
2013
 
 
2014
  line = clean_lines.elided[linenum]        # get rid of comments and strings
 
2015
 
 
2016
  # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc.
 
2017
  for operator in ['==', '!=', '>=', '>', '<=', '<']:
 
2018
    if ReplaceableCheck(operator, current_macro, line):
 
2019
      error(filename, linenum, 'readability/check', 2,
 
2020
            'Consider using %s instead of %s(a %s b)' % (
 
2021
                _CHECK_REPLACEMENT[current_macro][operator],
 
2022
                current_macro, operator))
 
2023
      break
 
2024
 
 
2025
 
 
2026
def GetLineWidth(line):
 
2027
  """Determines the width of the line in column positions.
 
2028
 
 
2029
  Args:
 
2030
    line: A string, which may be a Unicode string.
 
2031
 
 
2032
  Returns:
 
2033
    The width of the line in column positions, accounting for Unicode
 
2034
    combining characters and wide characters.
 
2035
  """
 
2036
  if isinstance(line, unicode):
 
2037
    width = 0
 
2038
    for c in unicodedata.normalize('NFC', line):
 
2039
      if unicodedata.east_asian_width(c) in ('W', 'F'):
 
2040
        width += 2
 
2041
      elif not unicodedata.combining(c):
 
2042
        width += 1
 
2043
    return width
 
2044
  else:
 
2045
    return len(line)
 
2046
 
 
2047
 
 
2048
def CheckStyle(filename, clean_lines, linenum, file_extension, error):
 
2049
  """Checks rules from the 'C++ style rules' section of cppguide.html.
 
2050
 
 
2051
  Most of these rules are hard to test (naming, comment style), but we
 
2052
  do what we can.  In particular we check for 2-space indents, line lengths,
 
2053
  tab usage, spaces inside code, etc.
 
2054
 
 
2055
  Args:
 
2056
    filename: The name of the current file.
 
2057
    clean_lines: A CleansedLines instance containing the file.
 
2058
    linenum: The number of the line to check.
 
2059
    file_extension: The extension (without the dot) of the filename.
 
2060
    error: The function to call with any errors found.
 
2061
  """
 
2062
 
 
2063
  raw_lines = clean_lines.raw_lines
 
2064
  line = raw_lines[linenum]
 
2065
 
 
2066
  if line.find('\t') != -1:
 
2067
    error(filename, linenum, 'whitespace/tab', 1,
 
2068
          'Tab found; better to use spaces')
 
2069
 
 
2070
  # One or three blank spaces at the beginning of the line is weird; it's
 
2071
  # hard to reconcile that with 2-space indents.
 
2072
  # NOTE: here are the conditions rob pike used for his tests.  Mine aren't
 
2073
  # as sophisticated, but it may be worth becoming so:  RLENGTH==initial_spaces
 
2074
  # if(RLENGTH > 20) complain = 0;
 
2075
  # if(match($0, " +(error|private|public|protected):")) complain = 0;
 
2076
  # if(match(prev, "&& *$")) complain = 0;
 
2077
  # if(match(prev, "\\|\\| *$")) complain = 0;
 
2078
  # if(match(prev, "[\",=><] *$")) complain = 0;
 
2079
  # if(match($0, " <<")) complain = 0;
 
2080
  # if(match(prev, " +for \\(")) complain = 0;
 
2081
  # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
 
2082
  initial_spaces = 0
 
2083
  cleansed_line = clean_lines.elided[linenum]
 
2084
  while initial_spaces < len(line) and line[initial_spaces] == ' ':
 
2085
    initial_spaces += 1
 
2086
  if line and line[-1].isspace():
 
2087
    error(filename, linenum, 'whitespace/end_of_line', 4,
 
2088
          'Line ends in whitespace.  Consider deleting these extra spaces.')
 
2089
  # There are certain situations we allow one space, notably for labels
 
2090
  elif ((initial_spaces == 1 or initial_spaces == 3) and
 
2091
        not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
 
2092
    error(filename, linenum, 'whitespace/indent', 3,
 
2093
          'Weird number of spaces at line-start.  '
 
2094
          'Are you using a 2-space indent?')
 
2095
  # Labels should always be indented at least one space.
 
2096
  elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$',
 
2097
                                                          line):
 
2098
    error(filename, linenum, 'whitespace/labels', 4,
 
2099
          'Labels should always be indented at least one space.  '
 
2100
          'If this is a member-initializer list in a constructor or '
 
2101
          'the base class list in a class definition, the colon should '
 
2102
          'be on the following line.')
 
2103
 
 
2104
 
 
2105
  # Check if the line is a header guard.
 
2106
  is_header_guard = False
 
2107
  if file_extension == 'h':
 
2108
    cppvar = GetHeaderGuardCPPVariable(filename)
 
2109
    if (line.startswith('#ifndef %s' % cppvar) or
 
2110
        line.startswith('#define %s' % cppvar) or
 
2111
        line.startswith('#endif  // %s' % cppvar)):
 
2112
      is_header_guard = True
 
2113
  # #include lines and header guards can be long, since there's no clean way to
 
2114
  # split them.
 
2115
  #
 
2116
  # URLs can be long too.  It's possible to split these, but it makes them
 
2117
  # harder to cut&paste.
 
2118
  if (not line.startswith('#include') and not is_header_guard and
 
2119
      not Match(r'^\s*//.*http(s?)://\S*$', line)):
 
2120
    line_width = GetLineWidth(line)
 
2121
    if line_width > 100:
 
2122
      error(filename, linenum, 'whitespace/line_length', 4,
 
2123
            'Lines should very rarely be longer than 100 characters')
 
2124
    elif line_width > 80:
 
2125
      error(filename, linenum, 'whitespace/line_length', 2,
 
2126
            'Lines should be <= 80 characters long')
 
2127
 
 
2128
  if (cleansed_line.count(';') > 1 and
 
2129
      # for loops are allowed two ;'s (and may run over two lines).
 
2130
      cleansed_line.find('for') == -1 and
 
2131
      (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or
 
2132
       GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and
 
2133
      # It's ok to have many commands in a switch case that fits in 1 line
 
2134
      not ((cleansed_line.find('case ') != -1 or
 
2135
            cleansed_line.find('default:') != -1) and
 
2136
           cleansed_line.find('break;') != -1)):
 
2137
    error(filename, linenum, 'whitespace/newline', 4,
 
2138
          'More than one command on the same line')
 
2139
 
 
2140
  # Some more style checks
 
2141
  CheckBraces(filename, clean_lines, linenum, error)
 
2142
  CheckSpacing(filename, clean_lines, linenum, error)
 
2143
  CheckCheck(filename, clean_lines, linenum, error)
 
2144
 
 
2145
 
 
2146
_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
 
2147
_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
 
2148
# Matches the first component of a filename delimited by -s and _s. That is:
 
2149
#  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
 
2150
#  _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo'
 
2151
#  _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo'
 
2152
#  _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo'
 
2153
_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
 
2154
 
 
2155
 
 
2156
def _DropCommonSuffixes(filename):
 
2157
  """Drops common suffixes like _test.cc or -inl.h from filename.
 
2158
 
 
2159
  For example:
 
2160
    >>> _DropCommonSuffixes('foo/foo-inl.h')
 
2161
    'foo/foo'
 
2162
    >>> _DropCommonSuffixes('foo/bar/foo.cc')
 
2163
    'foo/bar/foo'
 
2164
    >>> _DropCommonSuffixes('foo/foo_internal.h')
 
2165
    'foo/foo'
 
2166
    >>> _DropCommonSuffixes('foo/foo_unusualinternal.h')
 
2167
    'foo/foo_unusualinternal'
 
2168
 
 
2169
  Args:
 
2170
    filename: The input filename.
 
2171
 
 
2172
  Returns:
 
2173
    The filename with the common suffix removed.
 
2174
  """
 
2175
  for suffix in ('test.cc', 'regtest.cc', 'unittest.cc',
 
2176
                 'inl.h', 'impl.h', 'internal.h'):
 
2177
    if (filename.endswith(suffix) and len(filename) > len(suffix) and
 
2178
        filename[-len(suffix) - 1] in ('-', '_')):
 
2179
      return filename[:-len(suffix) - 1]
 
2180
  return os.path.splitext(filename)[0]
 
2181
 
 
2182
 
 
2183
def _IsTestFilename(filename):
 
2184
  """Determines if the given filename has a suffix that identifies it as a test.
 
2185
 
 
2186
  Args:
 
2187
    filename: The input filename.
 
2188
 
 
2189
  Returns:
 
2190
    True if 'filename' looks like a test, False otherwise.
 
2191
  """
 
2192
  if (filename.endswith('_test.cc') or
 
2193
      filename.endswith('_unittest.cc') or
 
2194
      filename.endswith('_regtest.cc')):
 
2195
    return True
 
2196
  else:
 
2197
    return False
 
2198
 
 
2199
 
 
2200
def _ClassifyInclude(fileinfo, include, is_system):
 
2201
  """Figures out what kind of header 'include' is.
 
2202
 
 
2203
  Args:
 
2204
    fileinfo: The current file cpplint is running over. A FileInfo instance.
 
2205
    include: The path to a #included file.
 
2206
    is_system: True if the #include used <> rather than "".
 
2207
 
 
2208
  Returns:
 
2209
    One of the _XXX_HEADER constants.
 
2210
 
 
2211
  For example:
 
2212
    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True)
 
2213
    _C_SYS_HEADER
 
2214
    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True)
 
2215
    _CPP_SYS_HEADER
 
2216
    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False)
 
2217
    _LIKELY_MY_HEADER
 
2218
    >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'),
 
2219
    ...                  'bar/foo_other_ext.h', False)
 
2220
    _POSSIBLE_MY_HEADER
 
2221
    >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False)
 
2222
    _OTHER_HEADER
 
2223
  """
 
2224
  # This is a list of all standard c++ header files, except
 
2225
  # those already checked for above.
 
2226
  is_stl_h = include in _STL_HEADERS
 
2227
  is_cpp_h = is_stl_h or include in _CPP_HEADERS
 
2228
 
 
2229
  if is_system:
 
2230
    if is_cpp_h:
 
2231
      return _CPP_SYS_HEADER
 
2232
    else:
 
2233
      return _C_SYS_HEADER
 
2234
 
 
2235
  # If the target file and the include we're checking share a
 
2236
  # basename when we drop common extensions, and the include
 
2237
  # lives in . , then it's likely to be owned by the target file.
 
2238
  target_dir, target_base = (
 
2239
      os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName())))
 
2240
  include_dir, include_base = os.path.split(_DropCommonSuffixes(include))
 
2241
  if target_base == include_base and (
 
2242
      include_dir == target_dir or
 
2243
      include_dir == os.path.normpath(target_dir + '/../public')):
 
2244
    return _LIKELY_MY_HEADER
 
2245
 
 
2246
  # If the target and include share some initial basename
 
2247
  # component, it's possible the target is implementing the
 
2248
  # include, so it's allowed to be first, but we'll never
 
2249
  # complain if it's not there.
 
2250
  target_first_component = _RE_FIRST_COMPONENT.match(target_base)
 
2251
  include_first_component = _RE_FIRST_COMPONENT.match(include_base)
 
2252
  if (target_first_component and include_first_component and
 
2253
      target_first_component.group(0) ==
 
2254
      include_first_component.group(0)):
 
2255
    return _POSSIBLE_MY_HEADER
 
2256
 
 
2257
  return _OTHER_HEADER
 
2258
 
 
2259
 
 
2260
 
 
2261
def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
 
2262
  """Check rules that are applicable to #include lines.
 
2263
 
 
2264
  Strings on #include lines are NOT removed from elided line, to make
 
2265
  certain tasks easier. However, to prevent false positives, checks
 
2266
  applicable to #include lines in CheckLanguage must be put here.
 
2267
 
 
2268
  Args:
 
2269
    filename: The name of the current file.
 
2270
    clean_lines: A CleansedLines instance containing the file.
 
2271
    linenum: The number of the line to check.
 
2272
    include_state: An _IncludeState instance in which the headers are inserted.
 
2273
    error: The function to call with any errors found.
 
2274
  """
 
2275
  fileinfo = FileInfo(filename)
 
2276
 
 
2277
  line = clean_lines.lines[linenum]
 
2278
 
 
2279
  # "include" should use the new style "foo/bar.h" instead of just "bar.h"
 
2280
  if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line):
 
2281
    error(filename, linenum, 'build/include', 4,
 
2282
          'Include the directory when naming .h files')
 
2283
 
 
2284
  # we shouldn't include a file more than once. actually, there are a
 
2285
  # handful of instances where doing so is okay, but in general it's
 
2286
  # not.
 
2287
  match = _RE_PATTERN_INCLUDE.search(line)
 
2288
  if match:
 
2289
    include = match.group(2)
 
2290
    is_system = (match.group(1) == '<')
 
2291
    if include in include_state:
 
2292
      error(filename, linenum, 'build/include', 4,
 
2293
            '"%s" already included at %s:%s' %
 
2294
            (include, filename, include_state[include]))
 
2295
    else:
 
2296
      include_state[include] = linenum
 
2297
 
 
2298
      # We want to ensure that headers appear in the right order:
 
2299
      # 1) for foo.cc, foo.h  (preferred location)
 
2300
      # 2) c system files
 
2301
      # 3) cpp system files
 
2302
      # 4) for foo.cc, foo.h  (deprecated location)
 
2303
      # 5) other google headers
 
2304
      #
 
2305
      # We classify each include statement as one of those 5 types
 
2306
      # using a number of techniques. The include_state object keeps
 
2307
      # track of the highest type seen, and complains if we see a
 
2308
      # lower type after that.
 
2309
      error_message = include_state.CheckNextIncludeOrder(
 
2310
          _ClassifyInclude(fileinfo, include, is_system))
 
2311
      if error_message:
 
2312
        error(filename, linenum, 'build/include_order', 4,
 
2313
              '%s. Should be: %s.h, c system, c++ system, other.' %
 
2314
              (error_message, fileinfo.BaseName()))
 
2315
      if not include_state.IsInAlphabeticalOrder(include):
 
2316
        error(filename, linenum, 'build/include_alpha', 4,
 
2317
              'Include "%s" not in alphabetical order' % include)
 
2318
 
 
2319
  # Look for any of the stream classes that are part of standard C++.
 
2320
  match = _RE_PATTERN_INCLUDE.match(line)
 
2321
  if match:
 
2322
    include = match.group(2)
 
2323
    if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
 
2324
      # Many unit tests use cout, so we exempt them.
 
2325
      if not _IsTestFilename(filename):
 
2326
        error(filename, linenum, 'readability/streams', 3,
 
2327
              'Streams are highly discouraged.')
 
2328
 
 
2329
def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
 
2330
                  error):
 
2331
  """Checks rules from the 'C++ language rules' section of cppguide.html.
 
2332
 
 
2333
  Some of these rules are hard to test (function overloading, using
 
2334
  uint32 inappropriately), but we do the best we can.
 
2335
 
 
2336
  Args:
 
2337
    filename: The name of the current file.
 
2338
    clean_lines: A CleansedLines instance containing the file.
 
2339
    linenum: The number of the line to check.
 
2340
    file_extension: The extension (without the dot) of the filename.
 
2341
    include_state: An _IncludeState instance in which the headers are inserted.
 
2342
    error: The function to call with any errors found.
 
2343
  """
 
2344
  # If the line is empty or consists of entirely a comment, no need to
 
2345
  # check it.
 
2346
  line = clean_lines.elided[linenum]
 
2347
  if not line:
 
2348
    return
 
2349
 
 
2350
  match = _RE_PATTERN_INCLUDE.search(line)
 
2351
  if match:
 
2352
    CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
 
2353
    return
 
2354
 
 
2355
  # Create an extended_line, which is the concatenation of the current and
 
2356
  # next lines, for more effective checking of code that may span more than one
 
2357
  # line.
 
2358
  if linenum + 1 < clean_lines.NumLines():
 
2359
    extended_line = line + clean_lines.elided[linenum + 1]
 
2360
  else:
 
2361
    extended_line = line
 
2362
 
 
2363
  # Make Windows paths like Unix.
 
2364
  fullname = os.path.abspath(filename).replace('\\', '/')
 
2365
 
 
2366
  # TODO(unknown): figure out if they're using default arguments in fn proto.
 
2367
 
 
2368
  # Check for non-const references in functions.  This is tricky because &
 
2369
  # is also used to take the address of something.  We allow <> for templates,
 
2370
  # (ignoring whatever is between the braces) and : for classes.
 
2371
  # These are complicated re's.  They try to capture the following:
 
2372
  # paren (for fn-prototype start), typename, &, varname.  For the const
 
2373
  # version, we're willing for const to be before typename or after
 
2374
  # Don't check the implemention on same line.
 
2375
  fnline = line.split('{', 1)[0]
 
2376
  if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) >
 
2377
      len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?'
 
2378
                     r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) +
 
2379
      len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+',
 
2380
                     fnline))):
 
2381
 
 
2382
    # We allow non-const references in a few standard places, like functions
 
2383
    # called "swap()" or iostream operators like "<<" or ">>".
 
2384
    if not Search(
 
2385
        r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&',
 
2386
        fnline):
 
2387
      error(filename, linenum, 'runtime/references', 2,
 
2388
            'Is this a non-const reference? '
 
2389
            'If so, make const or use a pointer.')
 
2390
 
 
2391
  # Check to see if they're using an conversion function cast.
 
2392
  # I just try to capture the most common basic types, though there are more.
 
2393
  # Parameterless conversion functions, such as bool(), are allowed as they are
 
2394
  # probably a member operator declaration or default constructor.
 
2395
  match = Search(
 
2396
      r'(\bnew\s+)?\b'  # Grab 'new' operator, if it's there
 
2397
      r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line)
 
2398
  if match:
 
2399
    # gMock methods are defined using some variant of MOCK_METHODx(name, type)
 
2400
    # where type may be float(), int(string), etc.  Without context they are
 
2401
    # virtually indistinguishable from int(x) casts.
 
2402
    if (match.group(1) is None and  # If new operator, then this isn't a cast
 
2403
        not Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)):
 
2404
      error(filename, linenum, 'readability/casting', 4,
 
2405
            'Using deprecated casting style.  '
 
2406
            'Use static_cast<%s>(...) instead' %
 
2407
            match.group(2))
 
2408
 
 
2409
  CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
 
2410
                  'static_cast',
 
2411
                  r'\((int|float|double|bool|char|u?int(16|32|64))\)',
 
2412
                  error)
 
2413
  # This doesn't catch all cases.  Consider (const char * const)"hello".
 
2414
  CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
 
2415
                  'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
 
2416
 
 
2417
  # In addition, we look for people taking the address of a cast.  This
 
2418
  # is dangerous -- casts can assign to temporaries, so the pointer doesn't
 
2419
  # point where you think.
 
2420
  if Search(
 
2421
      r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line):
 
2422
    error(filename, linenum, 'runtime/casting', 4,
 
2423
          ('Are you taking an address of a cast?  '
 
2424
           'This is dangerous: could be a temp var.  '
 
2425
           'Take the address before doing the cast, rather than after'))
 
2426
 
 
2427
  # Check for people declaring static/global STL strings at the top level.
 
2428
  # This is dangerous because the C++ language does not guarantee that
 
2429
  # globals with constructors are initialized before the first access.
 
2430
  match = Match(
 
2431
      r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
 
2432
      line)
 
2433
  # Make sure it's not a function.
 
2434
  # Function template specialization looks like: "string foo<Type>(...".
 
2435
  # Class template definitions look like: "string Foo<Type>::Method(...".
 
2436
  if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)',
 
2437
                         match.group(3)):
 
2438
    error(filename, linenum, 'runtime/string', 4,
 
2439
          'For a static/global string constant, use a C style string instead: '
 
2440
          '"%schar %s[]".' %
 
2441
          (match.group(1), match.group(2)))
 
2442
 
 
2443
  # Check that we're not using RTTI outside of testing code.
 
2444
  if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename):
 
2445
    error(filename, linenum, 'runtime/rtti', 5,
 
2446
          'Do not use dynamic_cast<>.  If you need to cast within a class '
 
2447
          "hierarchy, use static_cast<> to upcast.  Google doesn't support "
 
2448
          'RTTI.')
 
2449
 
 
2450
  if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
 
2451
    error(filename, linenum, 'runtime/init', 4,
 
2452
          'You seem to be initializing a member variable with itself.')
 
2453
 
 
2454
  if file_extension == 'h':
 
2455
    # TODO(unknown): check that 1-arg constructors are explicit.
 
2456
    #                How to tell it's a constructor?
 
2457
    #                (handled in CheckForNonStandardConstructs for now)
 
2458
    # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
 
2459
    #                (level 1 error)
 
2460
    pass
 
2461
 
 
2462
  # Check if people are using the verboten C basic types.  The only exception
 
2463
  # we regularly allow is "unsigned short port" for port.
 
2464
  if Search(r'\bshort port\b', line):
 
2465
    if not Search(r'\bunsigned short port\b', line):
 
2466
      error(filename, linenum, 'runtime/int', 4,
 
2467
            'Use "unsigned short" for ports, not "short"')
 
2468
  else:
 
2469
    match = Search(r'\b(short|long(?! +double)|long long)\b', line)
 
2470
    if match:
 
2471
      error(filename, linenum, 'runtime/int', 4,
 
2472
            'Use int16/int64/etc, rather than the C type %s' % match.group(1))
 
2473
 
 
2474
  # When snprintf is used, the second argument shouldn't be a literal.
 
2475
  match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
 
2476
  if match and match.group(2) != '0':
 
2477
    # If 2nd arg is zero, snprintf is used to calculate size.
 
2478
    error(filename, linenum, 'runtime/printf', 3,
 
2479
          'If you can, use sizeof(%s) instead of %s as the 2nd arg '
 
2480
          'to snprintf.' % (match.group(1), match.group(2)))
 
2481
 
 
2482
  # Check if some verboten C functions are being used.
 
2483
  if Search(r'\bsprintf\b', line):
 
2484
    error(filename, linenum, 'runtime/printf', 5,
 
2485
          'Never use sprintf.  Use snprintf instead.')
 
2486
  match = Search(r'\b(strcpy|strcat)\b', line)
 
2487
  if match:
 
2488
    error(filename, linenum, 'runtime/printf', 4,
 
2489
          'Almost always, snprintf is better than %s' % match.group(1))
 
2490
 
 
2491
  if Search(r'\bsscanf\b', line):
 
2492
    error(filename, linenum, 'runtime/printf', 1,
 
2493
          'sscanf can be ok, but is slow and can overflow buffers.')
 
2494
 
 
2495
  # Check if some verboten operator overloading is going on
 
2496
  # TODO(unknown): catch out-of-line unary operator&:
 
2497
  #   class X {};
 
2498
  #   int operator&(const X& x) { return 42; }  // unary operator&
 
2499
  # The trick is it's hard to tell apart from binary operator&:
 
2500
  #   class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
 
2501
  if Search(r'\boperator\s*&\s*\(\s*\)', line):
 
2502
    error(filename, linenum, 'runtime/operator', 4,
 
2503
          'Unary operator& is dangerous.  Do not use it.')
 
2504
 
 
2505
  # Check for suspicious usage of "if" like
 
2506
  # } if (a == b) {
 
2507
  if Search(r'\}\s*if\s*\(', line):
 
2508
    error(filename, linenum, 'readability/braces', 4,
 
2509
          'Did you mean "else if"? If not, start a new line for "if".')
 
2510
 
 
2511
  # Check for potential format string bugs like printf(foo).
 
2512
  # We constrain the pattern not to pick things like DocidForPrintf(foo).
 
2513
  # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
 
2514
  match = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I)
 
2515
  if match:
 
2516
    error(filename, linenum, 'runtime/printf', 4,
 
2517
          'Potential format string bug. Do %s("%%s", %s) instead.'
 
2518
          % (match.group(1), match.group(2)))
 
2519
 
 
2520
  # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
 
2521
  match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
 
2522
  if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
 
2523
    error(filename, linenum, 'runtime/memset', 4,
 
2524
          'Did you mean "memset(%s, 0, %s)"?'
 
2525
          % (match.group(1), match.group(2)))
 
2526
 
 
2527
  if Search(r'\busing namespace\b', line):
 
2528
    error(filename, linenum, 'build/namespaces', 5,
 
2529
          'Do not use namespace using-directives.  '
 
2530
          'Use using-declarations instead.')
 
2531
 
 
2532
  # Detect variable-length arrays.
 
2533
  match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
 
2534
  if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
 
2535
      match.group(3).find(']') == -1):
 
2536
    # Split the size using space and arithmetic operators as delimiters.
 
2537
    # If any of the resulting tokens are not compile time constants then
 
2538
    # report the error.
 
2539
    tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
 
2540
    is_const = True
 
2541
    skip_next = False
 
2542
    for tok in tokens:
 
2543
      if skip_next:
 
2544
        skip_next = False
 
2545
        continue
 
2546
 
 
2547
      if Search(r'sizeof\(.+\)', tok): continue
 
2548
      if Search(r'arraysize\(\w+\)', tok): continue
 
2549
 
 
2550
      tok = tok.lstrip('(')
 
2551
      tok = tok.rstrip(')')
 
2552
      if not tok: continue
 
2553
      if Match(r'\d+', tok): continue
 
2554
      if Match(r'0[xX][0-9a-fA-F]+', tok): continue
 
2555
      if Match(r'k[A-Z0-9]\w*', tok): continue
 
2556
      if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
 
2557
      if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
 
2558
      # A catch all for tricky sizeof cases, including 'sizeof expression',
 
2559
      # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
 
2560
      # requires skipping the next token becasue we split on ' ' and '*'.
 
2561
      if tok.startswith('sizeof'):
 
2562
        skip_next = True
 
2563
        continue
 
2564
      is_const = False
 
2565
      break
 
2566
    if not is_const:
 
2567
      error(filename, linenum, 'runtime/arrays', 1,
 
2568
            'Do not use variable-length arrays.  Use an appropriately named '
 
2569
            "('k' followed by CamelCase) compile-time constant for the size.")
 
2570
 
 
2571
  # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
 
2572
  # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
 
2573
  # in the class declaration.
 
2574
  match = Match(
 
2575
      (r'\s*'
 
2576
       r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
 
2577
       r'\(.*\);$'),
 
2578
      line)
 
2579
  if match and linenum + 1 < clean_lines.NumLines():
 
2580
    next_line = clean_lines.elided[linenum + 1]
 
2581
    if not Search(r'^\s*};', next_line):
 
2582
      error(filename, linenum, 'readability/constructors', 3,
 
2583
            match.group(1) + ' should be the last thing in the class')
 
2584
 
 
2585
  # Check for use of unnamed namespaces in header files.  Registration
 
2586
  # macros are typically OK, so we allow use of "namespace {" on lines
 
2587
  # that end with backslashes.
 
2588
  if (file_extension == 'h'
 
2589
      and Search(r'\bnamespace\s*{', line)
 
2590
      and line[-1] != '\\'):
 
2591
    error(filename, linenum, 'build/namespaces', 4,
 
2592
          'Do not use unnamed namespaces in header files.  See '
 
2593
          'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
 
2594
          ' for more information.')
 
2595
 
 
2596
 
 
2597
def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
 
2598
                    error):
 
2599
  """Checks for a C-style cast by looking for the pattern.
 
2600
 
 
2601
  This also handles sizeof(type) warnings, due to similarity of content.
 
2602
 
 
2603
  Args:
 
2604
    filename: The name of the current file.
 
2605
    linenum: The number of the line to check.
 
2606
    line: The line of code to check.
 
2607
    raw_line: The raw line of code to check, with comments.
 
2608
    cast_type: The string for the C++ cast to recommend.  This is either
 
2609
      reinterpret_cast or static_cast, depending.
 
2610
    pattern: The regular expression used to find C-style casts.
 
2611
    error: The function to call with any errors found.
 
2612
  """
 
2613
  match = Search(pattern, line)
 
2614
  if not match:
 
2615
    return
 
2616
 
 
2617
  # e.g., sizeof(int)
 
2618
  sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
 
2619
  if sizeof_match:
 
2620
    error(filename, linenum, 'runtime/sizeof', 1,
 
2621
          'Using sizeof(type).  Use sizeof(varname) instead if possible')
 
2622
    return
 
2623
 
 
2624
  remainder = line[match.end(0):]
 
2625
 
 
2626
  # The close paren is for function pointers as arguments to a function.
 
2627
  # eg, void foo(void (*bar)(int));
 
2628
  # The semicolon check is a more basic function check; also possibly a
 
2629
  # function pointer typedef.
 
2630
  # eg, void foo(int); or void foo(int) const;
 
2631
  # The equals check is for function pointer assignment.
 
2632
  # eg, void *(*foo)(int) = ...
 
2633
  #
 
2634
  # Right now, this will only catch cases where there's a single argument, and
 
2635
  # it's unnamed.  It should probably be expanded to check for multiple
 
2636
  # arguments with some unnamed.
 
2637
  function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder)
 
2638
  if function_match:
 
2639
    if (not function_match.group(3) or
 
2640
        function_match.group(3) == ';' or
 
2641
        raw_line.find('/*') < 0):
 
2642
      error(filename, linenum, 'readability/function', 3,
 
2643
            'All parameters should be named in a function')
 
2644
    return
 
2645
 
 
2646
  # At this point, all that should be left is actual casts.
 
2647
  error(filename, linenum, 'readability/casting', 4,
 
2648
        'Using C-style cast.  Use %s<%s>(...) instead' %
 
2649
        (cast_type, match.group(1)))
 
2650
 
 
2651
 
 
2652
_HEADERS_CONTAINING_TEMPLATES = (
 
2653
    ('<deque>', ('deque',)),
 
2654
    ('<functional>', ('unary_function', 'binary_function',
 
2655
                      'plus', 'minus', 'multiplies', 'divides', 'modulus',
 
2656
                      'negate',
 
2657
                      'equal_to', 'not_equal_to', 'greater', 'less',
 
2658
                      'greater_equal', 'less_equal',
 
2659
                      'logical_and', 'logical_or', 'logical_not',
 
2660
                      'unary_negate', 'not1', 'binary_negate', 'not2',
 
2661
                      'bind1st', 'bind2nd',
 
2662
                      'pointer_to_unary_function',
 
2663
                      'pointer_to_binary_function',
 
2664
                      'ptr_fun',
 
2665
                      'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
 
2666
                      'mem_fun_ref_t',
 
2667
                      'const_mem_fun_t', 'const_mem_fun1_t',
 
2668
                      'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
 
2669
                      'mem_fun_ref',
 
2670
                     )),
 
2671
    ('<limits>', ('numeric_limits',)),
 
2672
    ('<list>', ('list',)),
 
2673
    ('<map>', ('map', 'multimap',)),
 
2674
    ('<memory>', ('allocator',)),
 
2675
    ('<queue>', ('queue', 'priority_queue',)),
 
2676
    ('<set>', ('set', 'multiset',)),
 
2677
    ('<stack>', ('stack',)),
 
2678
    ('<string>', ('char_traits', 'basic_string',)),
 
2679
    ('<utility>', ('pair',)),
 
2680
    ('<vector>', ('vector',)),
 
2681
 
 
2682
    # gcc extensions.
 
2683
    # Note: std::hash is their hash, ::hash is our hash
 
2684
    ('<hash_map>', ('hash_map', 'hash_multimap',)),
 
2685
    ('<hash_set>', ('hash_set', 'hash_multiset',)),
 
2686
    ('<slist>', ('slist',)),
 
2687
    )
 
2688
 
 
2689
_HEADERS_ACCEPTED_BUT_NOT_PROMOTED = {
 
2690
    # We can trust with reasonable confidence that map gives us pair<>, too.
 
2691
    'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap')
 
2692
}
 
2693
 
 
2694
_RE_PATTERN_STRING = re.compile(r'\bstring\b')
 
2695
 
 
2696
_re_pattern_algorithm_header = []
 
2697
for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
 
2698
                  'transform'):
 
2699
  # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
 
2700
  # type::max().
 
2701
  _re_pattern_algorithm_header.append(
 
2702
      (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
 
2703
       _template,
 
2704
       '<algorithm>'))
 
2705
 
 
2706
_re_pattern_templates = []
 
2707
for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
 
2708
  for _template in _templates:
 
2709
    _re_pattern_templates.append(
 
2710
        (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
 
2711
         _template + '<>',
 
2712
         _header))
 
2713
 
 
2714
 
 
2715
def FilesBelongToSameModule(filename_cc, filename_h):
 
2716
  """Check if these two filenames belong to the same module.
 
2717
 
 
2718
  The concept of a 'module' here is a as follows:
 
2719
  foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the
 
2720
  same 'module' if they are in the same directory.
 
2721
  some/path/public/xyzzy and some/path/internal/xyzzy are also considered
 
2722
  to belong to the same module here.
 
2723
 
 
2724
  If the filename_cc contains a longer path than the filename_h, for example,
 
2725
  '/absolute/path/to/base/sysinfo.cc', and this file would include
 
2726
  'base/sysinfo.h', this function also produces the prefix needed to open the
 
2727
  header. This is used by the caller of this function to more robustly open the
 
2728
  header file. We don't have access to the real include paths in this context,
 
2729
  so we need this guesswork here.
 
2730
 
 
2731
  Known bugs: tools/base/bar.cc and base/bar.h belong to the same module
 
2732
  according to this implementation. Because of this, this function gives
 
2733
  some false positives. This should be sufficiently rare in practice.
 
2734
 
 
2735
  Args:
 
2736
    filename_cc: is the path for the .cc file
 
2737
    filename_h: is the path for the header path
 
2738
 
 
2739
  Returns:
 
2740
    Tuple with a bool and a string:
 
2741
    bool: True if filename_cc and filename_h belong to the same module.
 
2742
    string: the additional prefix needed to open the header file.
 
2743
  """
 
2744
 
 
2745
  if not filename_cc.endswith('.cc'):
 
2746
    return (False, '')
 
2747
  filename_cc = filename_cc[:-len('.cc')]
 
2748
  if filename_cc.endswith('_unittest'):
 
2749
    filename_cc = filename_cc[:-len('_unittest')]
 
2750
  elif filename_cc.endswith('_test'):
 
2751
    filename_cc = filename_cc[:-len('_test')]
 
2752
  filename_cc = filename_cc.replace('/public/', '/')
 
2753
  filename_cc = filename_cc.replace('/internal/', '/')
 
2754
 
 
2755
  if not filename_h.endswith('.h'):
 
2756
    return (False, '')
 
2757
  filename_h = filename_h[:-len('.h')]
 
2758
  if filename_h.endswith('-inl'):
 
2759
    filename_h = filename_h[:-len('-inl')]
 
2760
  filename_h = filename_h.replace('/public/', '/')
 
2761
  filename_h = filename_h.replace('/internal/', '/')
 
2762
 
 
2763
  files_belong_to_same_module = filename_cc.endswith(filename_h)
 
2764
  common_path = ''
 
2765
  if files_belong_to_same_module:
 
2766
    common_path = filename_cc[:-len(filename_h)]
 
2767
  return files_belong_to_same_module, common_path
 
2768
 
 
2769
 
 
2770
def UpdateIncludeState(filename, include_state, io=codecs):
 
2771
  """Fill up the include_state with new includes found from the file.
 
2772
 
 
2773
  Args:
 
2774
    filename: the name of the header to read.
 
2775
    include_state: an _IncludeState instance in which the headers are inserted.
 
2776
    io: The io factory to use to read the file. Provided for testability.
 
2777
 
 
2778
  Returns:
 
2779
    True if a header was succesfully added. False otherwise.
 
2780
  """
 
2781
  headerfile = None
 
2782
  try:
 
2783
    headerfile = io.open(filename, 'r', 'utf8', 'replace')
 
2784
  except IOError:
 
2785
    return False
 
2786
  linenum = 0
 
2787
  for line in headerfile:
 
2788
    linenum += 1
 
2789
    clean_line = CleanseComments(line)
 
2790
    match = _RE_PATTERN_INCLUDE.search(clean_line)
 
2791
    if match:
 
2792
      include = match.group(2)
 
2793
      # The value formatting is cute, but not really used right now.
 
2794
      # What matters here is that the key is in include_state.
 
2795
      include_state.setdefault(include, '%s:%d' % (filename, linenum))
 
2796
  return True
 
2797
 
 
2798
 
 
2799
def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
 
2800
                              io=codecs):
 
2801
  """Reports for missing stl includes.
 
2802
 
 
2803
  This function will output warnings to make sure you are including the headers
 
2804
  necessary for the stl containers and functions that you use. We only give one
 
2805
  reason to include a header. For example, if you use both equal_to<> and
 
2806
  less<> in a .h file, only one (the latter in the file) of these will be
 
2807
  reported as a reason to include the <functional>.
 
2808
 
 
2809
  Args:
 
2810
    filename: The name of the current file.
 
2811
    clean_lines: A CleansedLines instance containing the file.
 
2812
    include_state: An _IncludeState instance.
 
2813
    error: The function to call with any errors found.
 
2814
    io: The IO factory to use to read the header file. Provided for unittest
 
2815
        injection.
 
2816
  """
 
2817
  required = {}  # A map of header name to linenumber and the template entity.
 
2818
                 # Example of required: { '<functional>': (1219, 'less<>') }
 
2819
 
 
2820
  for linenum in xrange(clean_lines.NumLines()):
 
2821
    line = clean_lines.elided[linenum]
 
2822
    if not line or line[0] == '#':
 
2823
      continue
 
2824
 
 
2825
    # String is special -- it is a non-templatized type in STL.
 
2826
    m = _RE_PATTERN_STRING.search(line)
 
2827
    if m:
 
2828
      # Don't warn about strings in non-STL namespaces:
 
2829
      # (We check only the first match per line; good enough.)
 
2830
      prefix = line[:m.start()]
 
2831
      if prefix.endswith('std::') or not prefix.endswith('::'):
 
2832
        required['<string>'] = (linenum, 'string')
 
2833
 
 
2834
    for pattern, template, header in _re_pattern_algorithm_header:
 
2835
      if pattern.search(line):
 
2836
        required[header] = (linenum, template)
 
2837
 
 
2838
    # The following function is just a speed up, no semantics are changed.
 
2839
    if not '<' in line:  # Reduces the cpu time usage by skipping lines.
 
2840
      continue
 
2841
 
 
2842
    for pattern, template, header in _re_pattern_templates:
 
2843
      if pattern.search(line):
 
2844
        required[header] = (linenum, template)
 
2845
 
 
2846
  # The policy is that if you #include something in foo.h you don't need to
 
2847
  # include it again in foo.cc. Here, we will look at possible includes.
 
2848
  # Let's copy the include_state so it is only messed up within this function.
 
2849
  include_state = include_state.copy()
 
2850
 
 
2851
  # Did we find the header for this file (if any) and succesfully load it?
 
2852
  header_found = False
 
2853
 
 
2854
  # Use the absolute path so that matching works properly.
 
2855
  abs_filename = os.path.abspath(filename)
 
2856
 
 
2857
  # For Emacs's flymake.
 
2858
  # If cpplint is invoked from Emacs's flymake, a temporary file is generated
 
2859
  # by flymake and that file name might end with '_flymake.cc'. In that case,
 
2860
  # restore original file name here so that the corresponding header file can be
 
2861
  # found.
 
2862
  # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
 
2863
  # instead of 'foo_flymake.h'
 
2864
  abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)
 
2865
 
 
2866
  # include_state is modified during iteration, so we iterate over a copy of
 
2867
  # the keys.
 
2868
  for header in include_state.keys():  #NOLINT
 
2869
    (same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
 
2870
    fullpath = common_path + header
 
2871
    if same_module and UpdateIncludeState(fullpath, include_state, io):
 
2872
      header_found = True
 
2873
 
 
2874
  # If we can't find the header file for a .cc, assume it's because we don't
 
2875
  # know where to look. In that case we'll give up as we're not sure they
 
2876
  # didn't include it in the .h file.
 
2877
  # TODO(unknown): Do a better job of finding .h files so we are confident that
 
2878
  # not having the .h file means there isn't one.
 
2879
  if filename.endswith('.cc') and not header_found:
 
2880
    return
 
2881
 
 
2882
  # All the lines have been processed, report the errors found.
 
2883
  for required_header_unstripped in required:
 
2884
    template = required[required_header_unstripped][1]
 
2885
    if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED:
 
2886
      headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template]
 
2887
      if [True for header in headers if header in include_state]:
 
2888
        continue
 
2889
    if required_header_unstripped.strip('<>"') not in include_state:
 
2890
      error(filename, required[required_header_unstripped][0],
 
2891
            'build/include_what_you_use', 4,
 
2892
            'Add #include ' + required_header_unstripped + ' for ' + template)
 
2893
 
 
2894
 
 
2895
def ProcessLine(filename, file_extension,
 
2896
                clean_lines, line, include_state, function_state,
 
2897
                class_state, error):
 
2898
  """Processes a single line in the file.
 
2899
 
 
2900
  Args:
 
2901
    filename: Filename of the file that is being processed.
 
2902
    file_extension: The extension (dot not included) of the file.
 
2903
    clean_lines: An array of strings, each representing a line of the file,
 
2904
                 with comments stripped.
 
2905
    line: Number of line being processed.
 
2906
    include_state: An _IncludeState instance in which the headers are inserted.
 
2907
    function_state: A _FunctionState instance which counts function lines, etc.
 
2908
    class_state: A _ClassState instance which maintains information about
 
2909
                 the current stack of nested class declarations being parsed.
 
2910
    error: A callable to which errors are reported, which takes 4 arguments:
 
2911
           filename, line number, error level, and message
 
2912
 
 
2913
  """
 
2914
  raw_lines = clean_lines.raw_lines
 
2915
  ParseNolintSuppressions(filename, raw_lines[line], line, error)
 
2916
  CheckForFunctionLengths(filename, clean_lines, line, function_state, error)
 
2917
  CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
 
2918
  CheckStyle(filename, clean_lines, line, file_extension, error)
 
2919
  CheckLanguage(filename, clean_lines, line, file_extension, include_state,
 
2920
                error)
 
2921
  CheckForNonStandardConstructs(filename, clean_lines, line,
 
2922
                                class_state, error)
 
2923
  CheckPosixThreading(filename, clean_lines, line, error)
 
2924
  CheckInvalidIncrement(filename, clean_lines, line, error)
 
2925
 
 
2926
 
 
2927
def ProcessFileData(filename, file_extension, lines, error):
 
2928
  """Performs lint checks and reports any errors to the given error function.
 
2929
 
 
2930
  Args:
 
2931
    filename: Filename of the file that is being processed.
 
2932
    file_extension: The extension (dot not included) of the file.
 
2933
    lines: An array of strings, each representing a line of the file, with the
 
2934
           last element being empty if the file is termined with a newline.
 
2935
    error: A callable to which errors are reported, which takes 4 arguments:
 
2936
  """
 
2937
  lines = (['// marker so line numbers and indices both start at 1'] + lines +
 
2938
           ['// marker so line numbers end in a known way'])
 
2939
 
 
2940
  include_state = _IncludeState()
 
2941
  function_state = _FunctionState()
 
2942
  class_state = _ClassState()
 
2943
 
 
2944
  ResetNolintSuppressions()
 
2945
 
 
2946
  CheckForCopyright(filename, lines, error)
 
2947
 
 
2948
  if file_extension == 'h':
 
2949
    CheckForHeaderGuard(filename, lines, error)
 
2950
 
 
2951
  RemoveMultiLineComments(filename, lines, error)
 
2952
  clean_lines = CleansedLines(lines)
 
2953
  for line in xrange(clean_lines.NumLines()):
 
2954
    ProcessLine(filename, file_extension, clean_lines, line,
 
2955
                include_state, function_state, class_state, error)
 
2956
  class_state.CheckFinished(filename, error)
 
2957
 
 
2958
  CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
 
2959
 
 
2960
  # We check here rather than inside ProcessLine so that we see raw
 
2961
  # lines rather than "cleaned" lines.
 
2962
  CheckForUnicodeReplacementCharacters(filename, lines, error)
 
2963
 
 
2964
  CheckForNewlineAtEOF(filename, lines, error)
 
2965
 
 
2966
def ProcessFile(filename, vlevel):
 
2967
  """Does google-lint on a single file.
 
2968
 
 
2969
  Args:
 
2970
    filename: The name of the file to parse.
 
2971
 
 
2972
    vlevel: The level of errors to report.  Every error of confidence
 
2973
    >= verbose_level will be reported.  0 is a good default.
 
2974
  """
 
2975
 
 
2976
  _SetVerboseLevel(vlevel)
 
2977
 
 
2978
  try:
 
2979
    # Support the UNIX convention of using "-" for stdin.  Note that
 
2980
    # we are not opening the file with universal newline support
 
2981
    # (which codecs doesn't support anyway), so the resulting lines do
 
2982
    # contain trailing '\r' characters if we are reading a file that
 
2983
    # has CRLF endings.
 
2984
    # If after the split a trailing '\r' is present, it is removed
 
2985
    # below. If it is not expected to be present (i.e. os.linesep !=
 
2986
    # '\r\n' as in Windows), a warning is issued below if this file
 
2987
    # is processed.
 
2988
 
 
2989
    if filename == '-':
 
2990
      lines = codecs.StreamReaderWriter(sys.stdin,
 
2991
                                        codecs.getreader('utf8'),
 
2992
                                        codecs.getwriter('utf8'),
 
2993
                                        'replace').read().split('\n')
 
2994
    else:
 
2995
      lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
 
2996
 
 
2997
    carriage_return_found = False
 
2998
    # Remove trailing '\r'.
 
2999
    for linenum in range(len(lines)):
 
3000
      if lines[linenum].endswith('\r'):
 
3001
        lines[linenum] = lines[linenum].rstrip('\r')
 
3002
        carriage_return_found = True
 
3003
 
 
3004
  except IOError:
 
3005
    sys.stderr.write(
 
3006
        "Skipping input '%s': Can't open for reading\n" % filename)
 
3007
    return
 
3008
 
 
3009
  # Note, if no dot is found, this will give the entire filename as the ext.
 
3010
  file_extension = filename[filename.rfind('.') + 1:]
 
3011
 
 
3012
  # When reading from stdin, the extension is unknown, so no cpplint tests
 
3013
  # should rely on the extension.
 
3014
  if (filename != '-' and file_extension != 'cc' and file_extension != 'h'
 
3015
      and file_extension != 'cpp'):
 
3016
    sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename)
 
3017
  else:
 
3018
    ProcessFileData(filename, file_extension, lines, Error)
 
3019
    if carriage_return_found and os.linesep != '\r\n':
 
3020
      # Use 0 for linenum since outputing only one error for potentially
 
3021
      # several lines.
 
3022
      Error(filename, 0, 'whitespace/newline', 1,
 
3023
            'One or more unexpected \\r (^M) found;'
 
3024
            'better to use only a \\n')
 
3025
 
 
3026
  sys.stderr.write('Done processing %s\n' % filename)
 
3027
 
 
3028
 
 
3029
def PrintUsage(message):
 
3030
  """Prints a brief usage string and exits, optionally with an error message.
 
3031
 
 
3032
  Args:
 
3033
    message: The optional error message.
 
3034
  """
 
3035
  sys.stderr.write(_USAGE)
 
3036
  if message:
 
3037
    sys.exit('\nFATAL ERROR: ' + message)
 
3038
  else:
 
3039
    sys.exit(1)
 
3040
 
 
3041
 
 
3042
def PrintCategories():
 
3043
  """Prints a list of all the error-categories used by error messages.
 
3044
 
 
3045
  These are the categories used to filter messages via --filter.
 
3046
  """
 
3047
  sys.stderr.write(''.join('  %s\n' % cat for cat in _ERROR_CATEGORIES))
 
3048
  sys.exit(0)
 
3049
 
 
3050
 
 
3051
def ParseArguments(args):
 
3052
  """Parses the command line arguments.
 
3053
 
 
3054
  This may set the output format and verbosity level as side-effects.
 
3055
 
 
3056
  Args:
 
3057
    args: The command line arguments:
 
3058
 
 
3059
  Returns:
 
3060
    The list of filenames to lint.
 
3061
  """
 
3062
  try:
 
3063
    (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=',
 
3064
                                                 'counting=',
 
3065
                                                 'filter='])
 
3066
  except getopt.GetoptError:
 
3067
    PrintUsage('Invalid arguments.')
 
3068
 
 
3069
  verbosity = _VerboseLevel()
 
3070
  output_format = _OutputFormat()
 
3071
  filters = ''
 
3072
  counting_style = ''
 
3073
 
 
3074
  for (opt, val) in opts:
 
3075
    if opt == '--help':
 
3076
      PrintUsage(None)
 
3077
    elif opt == '--output':
 
3078
      if not val in ('emacs', 'vs7'):
 
3079
        PrintUsage('The only allowed output formats are emacs and vs7.')
 
3080
      output_format = val
 
3081
    elif opt == '--verbose':
 
3082
      verbosity = int(val)
 
3083
    elif opt == '--filter':
 
3084
      filters = val
 
3085
      if not filters:
 
3086
        PrintCategories()
 
3087
    elif opt == '--counting':
 
3088
      if val not in ('total', 'toplevel', 'detailed'):
 
3089
        PrintUsage('Valid counting options are total, toplevel, and detailed')
 
3090
      counting_style = val
 
3091
 
 
3092
  if not filenames:
 
3093
    PrintUsage('No files were specified.')
 
3094
 
 
3095
  _SetOutputFormat(output_format)
 
3096
  _SetVerboseLevel(verbosity)
 
3097
  _SetFilters(filters)
 
3098
  _SetCountingStyle(counting_style)
 
3099
 
 
3100
  return filenames
 
3101
 
 
3102
 
 
3103
def main():
 
3104
  filenames = ParseArguments(sys.argv[1:])
 
3105
 
 
3106
  # Change stderr to write with replacement characters so we don't die
 
3107
  # if we try to print something containing non-ASCII characters.
 
3108
  sys.stderr = codecs.StreamReaderWriter(sys.stderr,
 
3109
                                         codecs.getreader('utf8'),
 
3110
                                         codecs.getwriter('utf8'),
 
3111
                                         'replace')
 
3112
 
 
3113
  _cpplint_state.ResetErrorCounts()
 
3114
  for filename in filenames:
 
3115
    ProcessFile(filename, _cpplint_state.verbose_level)
 
3116
  _cpplint_state.PrintErrorCounts()
 
3117
 
 
3118
  sys.exit(_cpplint_state.error_count > 0)
 
3119
 
 
3120
 
 
3121
if __name__ == '__main__':
 
3122
  main()