~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to extra/cpplint.py

Merge trunk and resolve all conflicts.

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