~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to extra/cpplint.py

  • Committer: Monty Taylor
  • Date: 2010-12-26 03:15:44 UTC
  • mto: This revision was merged to the branch mainline in revision 2038.
  • Revision ID: mordred@inaugust.com-20101226031544-1cf3raipu53fnmyj
Through page.

Show diffs side-by-side

added added

removed removed

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