~jan.greis/maus/1811

« back to all changes in this revision

Viewing changes to tests/style/cpplint.py

  • Committer: Chris Rogers
  • Date: 2011-05-11 09:33:14 UTC
  • mfrom: (340.1.92 devel)
  • mto: This revision was merged to the branch mainline in revision 490.
  • Revision ID: chris.rogers@stfc.ac.uk-20110511093314-fcxrl52ve3pwnr6s
Virtual Planes and cpplint stuff

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