238f70dadd853d46e569742f453625e616ecc53c
[WebKit-https.git] / Tools / Scripts / webkitpy / style / checkers / cpp.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright (C) 2009, 2010 Google Inc. All rights reserved.
5 # Copyright (C) 2009 Torch Mobile Inc.
6 # Copyright (C) 2009 Apple Inc. All rights reserved.
7 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are
11 # met:
12 #
13 #    * Redistributions of source code must retain the above copyright
14 # notice, this list of conditions and the following disclaimer.
15 #    * Redistributions in binary form must reproduce the above
16 # copyright notice, this list of conditions and the following disclaimer
17 # in the documentation and/or other materials provided with the
18 # distribution.
19 #    * Neither the name of Google Inc. nor the names of its
20 # contributors may be used to endorse or promote products derived from
21 # this software without specific prior written permission.
22 #
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35 # This is the modified version of Google's cpplint. The original code is
36 # http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py
37
38 """Support for check-webkit-style."""
39
40 import codecs
41 import math  # for log
42 import os
43 import os.path
44 import re
45 import sre_compile
46 import string
47 import sys
48 import unicodedata
49
50 from webkitpy.common.memoized import memoized
51
52 # The key to use to provide a class to fake loading a header file.
53 INCLUDE_IO_INJECTION_KEY = 'include_header_io'
54
55 # Headers that we consider STL headers.
56 _STL_HEADERS = frozenset([
57     'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
58     'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
59     'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h',
60     'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',
61     'stl_alloc.h', 'stl_relops.h', 'type_traits.h',
62     'utility', 'vector', 'vector.h',
63     ])
64
65
66 # Non-STL C++ system headers.
67 _CPP_HEADERS = frozenset([
68     'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype',
69     'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath',
70     'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef',
71     'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype',
72     'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream',
73     'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip',
74     'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h',
75     'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h',
76     'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h',
77     'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h',
78     'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',
79     'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string',
80     'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray',
81     ])
82
83
84 # Assertion macros.  These are defined in base/logging.h and
85 # testing/base/gunit.h.  Note that the _M versions need to come first
86 # for substring matching to work.
87 _CHECK_MACROS = [
88     'DCHECK', 'CHECK',
89     'EXPECT_TRUE_M', 'EXPECT_TRUE',
90     'ASSERT_TRUE_M', 'ASSERT_TRUE',
91     'EXPECT_FALSE_M', 'EXPECT_FALSE',
92     'ASSERT_FALSE_M', 'ASSERT_FALSE',
93     ]
94
95 # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
96 _CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS])
97
98 for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
99                         ('>=', 'GE'), ('>', 'GT'),
100                         ('<=', 'LE'), ('<', 'LT')]:
101     _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement
102     _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
103     _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
104     _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
105     _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
106     _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
107
108 for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
109                             ('>=', 'LT'), ('>', 'LE'),
110                             ('<=', 'GT'), ('<', 'GE')]:
111     _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
112     _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
113     _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
114     _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
115
116
117 # These constants define types of headers for use with
118 # _IncludeState.check_next_include_order().
119 _CONFIG_HEADER = 0
120 _PRIMARY_HEADER = 1
121 _OTHER_HEADER = 2
122 _MOC_HEADER = 3
123
124
125 # A dictionary of items customize behavior for unit test. For example,
126 # INCLUDE_IO_INJECTION_KEY allows providing a custom io class which allows
127 # for faking a header file.
128 _unit_test_config = {}
129
130
131 # The regexp compilation caching is inlined in all regexp functions for
132 # performance reasons; factoring it out into a separate function turns out
133 # to be noticeably expensive.
134 _regexp_compile_cache = {}
135
136
137 def match(pattern, s):
138     """Matches the string with the pattern, caching the compiled regexp."""
139     if not pattern in _regexp_compile_cache:
140         _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
141     return _regexp_compile_cache[pattern].match(s)
142
143
144 def search(pattern, s):
145     """Searches the string for the pattern, caching the compiled regexp."""
146     if not pattern in _regexp_compile_cache:
147         _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
148     return _regexp_compile_cache[pattern].search(s)
149
150
151 def sub(pattern, replacement, s):
152     """Substitutes occurrences of a pattern, caching the compiled regexp."""
153     if not pattern in _regexp_compile_cache:
154         _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
155     return _regexp_compile_cache[pattern].sub(replacement, s)
156
157
158 def subn(pattern, replacement, s):
159     """Substitutes occurrences of a pattern, caching the compiled regexp."""
160     if not pattern in _regexp_compile_cache:
161         _regexp_compile_cache[pattern] = sre_compile.compile(pattern)
162     return _regexp_compile_cache[pattern].subn(replacement, s)
163
164
165 def iteratively_replace_matches_with_char(pattern, char_replacement, s):
166     """Returns the string with replacement done.
167
168     Every character in the match is replaced with char.
169     Due to the iterative nature, pattern should not match char or
170     there will be an infinite loop.
171
172     Example:
173       pattern = r'<[^>]>' # template parameters
174       char_replacement =  '_'
175       s =     'A<B<C, D>>'
176       Returns 'A_________'
177
178     Args:
179       pattern: The regex to match.
180       char_replacement: The character to put in place of every
181                         character of the match.
182       s: The string on which to do the replacements.
183
184     Returns:
185       True, if the given line is blank.
186     """
187     while True:
188         matched = search(pattern, s)
189         if not matched:
190             return s
191         start_match_index = matched.start(0)
192         end_match_index = matched.end(0)
193         match_length = end_match_index - start_match_index
194         s = s[:start_match_index] + char_replacement * match_length + s[end_match_index:]
195
196
197 def _rfind_in_lines(regex, lines, start_position, not_found_position):
198     """Does a reverse find starting at start position and going backwards until
199     a match is found.
200
201     Returns the position where the regex ended.
202     """
203     # Put the regex in a group and proceed it with a greedy expression that
204     # matches anything to ensure that we get the last possible match in a line.
205     last_in_line_regex = r'.*(' + regex + ')'
206     current_row = start_position.row
207
208     # Start with the given row and trim off everything past what may be matched.
209     current_line = lines[start_position.row][:start_position.column]
210     while True:
211         found_match = match(last_in_line_regex, current_line)
212         if found_match:
213             return Position(current_row, found_match.end(1))
214
215         # A match was not found so continue backward.
216         current_row -= 1
217         if current_row < 0:
218             return not_found_position
219         current_line = lines[current_row]
220
221
222 def _convert_to_lower_with_underscores(text):
223     """Converts all text strings in camelCase or PascalCase to lowers with underscores."""
224
225     # First add underscores before any capital letter followed by a lower case letter
226     # as long as it is in a word.
227     # (This put an underscore before Password but not P and A in WPAPassword).
228     text = sub(r'(?<=[A-Za-z0-9])([A-Z])(?=[a-z])', r'_\1', text)
229
230     # Next add underscores before capitals at the end of words if it was
231     # preceeded by lower case letter or number.
232     # (This puts an underscore before A in isA but not A in CBA).
233     text = sub(r'(?<=[a-z0-9])([A-Z])(?=\b)', r'_\1', text)
234
235     # Next add underscores when you have a captial letter which is followed by a capital letter
236     # but is not proceeded by one. (This puts an underscore before A in 'WordADay').
237     text = sub(r'(?<=[a-z0-9])([A-Z][A-Z_])', r'_\1', text)
238
239     return text.lower()
240
241
242
243 def _create_acronym(text):
244     """Creates an acronym for the given text."""
245     # Removes all lower case letters except those starting words.
246     text = sub(r'(?<!\b)[a-z]', '', text)
247     return text.upper()
248
249
250 def up_to_unmatched_closing_paren(s):
251     """Splits a string into two parts up to first unmatched ')'.
252
253     Args:
254       s: a string which is a substring of line after '('
255       (e.g., "a == (b + c))").
256
257     Returns:
258       A pair of strings (prefix before first unmatched ')',
259       remainder of s after first unmatched ')'), e.g.,
260       up_to_unmatched_closing_paren("a == (b + c)) { ")
261       returns "a == (b + c)", " {".
262       Returns None, None if there is no unmatched ')'
263
264     """
265     i = 1
266     for pos, c in enumerate(s):
267       if c == '(':
268         i += 1
269       elif c == ')':
270         i -= 1
271         if i == 0:
272           return s[:pos], s[pos + 1:]
273     return None, None
274
275 class _IncludeState(dict):
276     """Tracks line numbers for includes, and the order in which includes appear.
277
278     As a dict, an _IncludeState object serves as a mapping between include
279     filename and line number on which that file was included.
280
281     Call check_next_include_order() once for each header in the file, passing
282     in the type constants defined above. Calls in an illegal order will
283     raise an _IncludeError with an appropriate error message.
284
285     """
286     # self._section will move monotonically through this set. If it ever
287     # needs to move backwards, check_next_include_order will raise an error.
288     _INITIAL_SECTION = 0
289     _CONFIG_SECTION = 1
290     _PRIMARY_SECTION = 2
291     _OTHER_SECTION = 3
292
293     _TYPE_NAMES = {
294         _CONFIG_HEADER: 'WebCore config.h',
295         _PRIMARY_HEADER: 'header this file implements',
296         _OTHER_HEADER: 'other header',
297         _MOC_HEADER: 'moc file',
298         }
299     _SECTION_NAMES = {
300         _INITIAL_SECTION: "... nothing.",
301         _CONFIG_SECTION: "WebCore config.h.",
302         _PRIMARY_SECTION: 'a header this file implements.',
303         _OTHER_SECTION: 'other header.',
304         }
305
306     def __init__(self):
307         dict.__init__(self)
308         self._section = self._INITIAL_SECTION
309         self._visited_primary_section = False
310         self.header_types = dict();
311
312     def visited_primary_section(self):
313         return self._visited_primary_section
314
315     def check_next_include_order(self, header_type, file_is_header, primary_header_exists):
316         """Returns a non-empty error message if the next header is out of order.
317
318         This function also updates the internal state to be ready to check
319         the next include.
320
321         Args:
322           header_type: One of the _XXX_HEADER constants defined above.
323           file_is_header: Whether the file that owns this _IncludeState is itself a header
324
325         Returns:
326           The empty string if the header is in the right order, or an
327           error message describing what's wrong.
328
329         """
330         if header_type == _CONFIG_HEADER and file_is_header:
331             return 'Header file should not contain WebCore config.h.'
332         if header_type == _PRIMARY_HEADER and file_is_header:
333             return 'Header file should not contain itself.'
334         if header_type == _MOC_HEADER:
335             return ''
336
337         error_message = ''
338         if self._section != self._OTHER_SECTION:
339             before_error_message = ('Found %s before %s' %
340                                     (self._TYPE_NAMES[header_type],
341                                      self._SECTION_NAMES[self._section + 1]))
342         after_error_message = ('Found %s after %s' %
343                                 (self._TYPE_NAMES[header_type],
344                                  self._SECTION_NAMES[self._section]))
345
346         if header_type == _CONFIG_HEADER:
347             if self._section >= self._CONFIG_SECTION:
348                 error_message = after_error_message
349             self._section = self._CONFIG_SECTION
350         elif header_type == _PRIMARY_HEADER:
351             if self._section >= self._PRIMARY_SECTION:
352                 error_message = after_error_message
353             elif self._section < self._CONFIG_SECTION:
354                 error_message = before_error_message
355             self._section = self._PRIMARY_SECTION
356             self._visited_primary_section = True
357         else:
358             assert header_type == _OTHER_HEADER
359             if not file_is_header and self._section < self._PRIMARY_SECTION:
360                 if primary_header_exists:
361                     error_message = before_error_message
362             self._section = self._OTHER_SECTION
363
364         return error_message
365
366
367 class Position(object):
368     """Holds the position of something."""
369     def __init__(self, row, column):
370         self.row = row
371         self.column = column
372
373     def __str__(self):
374         return '(%s, %s)' % (self.row, self.column)
375
376     def __cmp__(self, other):
377         return self.row.__cmp__(other.row) or self.column.__cmp__(other.column)
378
379
380 class Parameter(object):
381     """Information about one function parameter."""
382     def __init__(self, parameter, parameter_name_index, row):
383         self.type = parameter[:parameter_name_index].strip()
384         # Remove any initializers from the parameter name (e.g. int i = 5).
385         self.name = sub(r'=.*', '', parameter[parameter_name_index:]).strip()
386         self.row = row
387
388     @memoized
389     def lower_with_underscores_name(self):
390         """Returns the parameter name in the lower with underscores format."""
391         return _convert_to_lower_with_underscores(self.name)
392
393
394 class SingleLineView(object):
395     """Converts multiple lines into a single line (with line breaks replaced by a
396        space) to allow for easier searching."""
397     def __init__(self, lines, start_position, end_position):
398         """Create a SingleLineView instance.
399
400         Args:
401           lines: a list of multiple lines to combine into a single line.
402           start_position: offset within lines of where to start the single line.
403           end_position: just after where to end (like a slice operation).
404         """
405         # Get the rows of interest.
406         trimmed_lines = lines[start_position.row:end_position.row + 1]
407
408         # Remove the columns on the last line that aren't included.
409         trimmed_lines[-1] = trimmed_lines[-1][:end_position.column]
410
411         # Remove the columns on the first line that aren't included.
412         trimmed_lines[0] = trimmed_lines[0][start_position.column:]
413
414         # Create a single line with all of the parameters.
415         self.single_line = ' '.join(trimmed_lines)
416
417         # Keep the row lengths, so we can calculate the original row number
418         # given a column in the single line (adding 1 due to the space added
419         # during the join).
420         self._row_lengths = [len(line) + 1 for line in trimmed_lines]
421         self._starting_row = start_position.row
422
423     def convert_column_to_row(self, single_line_column_number):
424         """Convert the column number from the single line into the original
425         line number.
426
427         Special cases:
428         * Columns in the added spaces are considered part of the previous line.
429         * Columns beyond the end of the line are consider part the last line
430         in the view."""
431         total_columns = 0
432         row_offset = 0
433         while row_offset < len(self._row_lengths) - 1 and single_line_column_number >= total_columns + self._row_lengths[row_offset]:
434             total_columns += self._row_lengths[row_offset]
435             row_offset += 1
436         return self._starting_row + row_offset
437
438
439 def create_skeleton_parameters(all_parameters):
440     """Converts a parameter list to a skeleton version.
441
442     The skeleton only has one word for the parameter name, one word for the type,
443     and commas after each parameter and only there. Everything in the skeleton
444     remains in the same columns as the original."""
445     all_simplifications = (
446         # Remove template parameters, function declaration parameters, etc.
447         r'(<[^<>]*?>)|(\([^\(\)]*?\))|(\{[^\{\}]*?\})',
448         # Remove all initializers.
449         r'=[^,]*',
450         # Remove :: and everything before it.
451         r'[^,]*::',
452         # Remove modifiers like &, *.
453         r'[&*]',
454         # Remove const modifiers.
455         r'\bconst\s+(?=[A-Za-z])',
456         # Remove numerical modifiers like long.
457         r'\b(unsigned|long|short)\s+(?=unsigned|long|short|int|char|double|float)')
458
459     skeleton_parameters = all_parameters
460     for simplification in all_simplifications:
461         skeleton_parameters = iteratively_replace_matches_with_char(simplification, ' ', skeleton_parameters)
462     # If there are any parameters, then add a , after the last one to
463     # make a regular pattern of a , following every parameter.
464     if skeleton_parameters.strip():
465         skeleton_parameters += ','
466     return skeleton_parameters
467
468
469 def find_parameter_name_index(skeleton_parameter):
470     """Determines where the parametere name starts given the skeleton parameter."""
471     # The first space from the right in the simplified parameter is where the parameter
472     # name starts unless the first space is before any content in the simplified parameter.
473     before_name_index = skeleton_parameter.rstrip().rfind(' ')
474     if before_name_index != -1 and skeleton_parameter[:before_name_index].strip():
475         return before_name_index + 1
476     return len(skeleton_parameter)
477
478
479 def parameter_list(elided_lines, start_position, end_position):
480     """Generator for a function's parameters."""
481     # Create new positions that omit the outer parenthesis of the parameters.
482     start_position = Position(row=start_position.row, column=start_position.column + 1)
483     end_position = Position(row=end_position.row, column=end_position.column - 1)
484     single_line_view = SingleLineView(elided_lines, start_position, end_position)
485     skeleton_parameters = create_skeleton_parameters(single_line_view.single_line)
486     end_index = -1
487
488     while True:
489         # Find the end of the next parameter.
490         start_index = end_index + 1
491         end_index = skeleton_parameters.find(',', start_index)
492
493         # No comma means that all parameters have been parsed.
494         if end_index == -1:
495             return
496         row = single_line_view.convert_column_to_row(end_index)
497
498         # Parse the parameter into a type and parameter name.
499         skeleton_parameter = skeleton_parameters[start_index:end_index]
500         name_offset = find_parameter_name_index(skeleton_parameter)
501         parameter = single_line_view.single_line[start_index:end_index]
502         yield Parameter(parameter, name_offset, row)
503
504
505 class _FunctionState(object):
506     """Tracks current function name and the number of lines in its body.
507
508     Attributes:
509       min_confidence: The minimum confidence level to use while checking style.
510
511     """
512
513     _NORMAL_TRIGGER = 250  # for --v=0, 500 for --v=1, etc.
514     _TEST_TRIGGER = 400    # about 50% more than _NORMAL_TRIGGER.
515
516     def __init__(self, min_confidence):
517         self.min_confidence = min_confidence
518         self.current_function = ''
519         self.in_a_function = False
520         self.lines_in_function = 0
521         # Make sure these will not be mistaken for real positions (even when a
522         # small amount is added to them).
523         self.body_start_position = Position(-1000, 0)
524         self.end_position = Position(-1000, 0)
525
526     def begin(self, function_name, function_name_start_position, body_start_position, end_position,
527               parameter_start_position, parameter_end_position, clean_lines):
528         """Start analyzing function body.
529
530         Args:
531             function_name: The name of the function being tracked.
532             function_name_start_position: Position in elided where the function name starts.
533             body_start_position: Position in elided of the { or the ; for a prototype.
534             end_position: Position in elided just after the final } (or ; is.
535             parameter_start_position: Position in elided of the '(' for the parameters.
536             parameter_end_position: Position in elided just after the ')' for the parameters.
537             clean_lines: A CleansedLines instance containing the file.
538         """
539         self.in_a_function = True
540         self.lines_in_function = -1  # Don't count the open brace line.
541         self.current_function = function_name
542         self.function_name_start_position = function_name_start_position
543         self.body_start_position = body_start_position
544         self.end_position = end_position
545         self.is_declaration = clean_lines.elided[body_start_position.row][body_start_position.column] == ';'
546         self.parameter_start_position = parameter_start_position
547         self.parameter_end_position = parameter_end_position
548         self.is_pure = False
549         if self.is_declaration:
550             characters_after_parameters = SingleLineView(clean_lines.elided, parameter_end_position, body_start_position).single_line
551             self.is_pure = bool(match(r'\s*=\s*0\s*', characters_after_parameters))
552         self._clean_lines = clean_lines
553         self._parameter_list = None
554
555     def modifiers_and_return_type(self):
556         """Returns the modifiers and the return type."""
557         # Go backwards from where the function name is until we encounter one of several things:
558         #   ';' or '{' or '}' or 'private:', etc. or '#' or return Position(0, 0)
559         elided = self._clean_lines.elided
560         start_modifiers = _rfind_in_lines(r';|\{|\}|((private|public|protected):)|(#.*)',
561                                           elided, self.parameter_start_position, Position(0, 0))
562         return SingleLineView(elided, start_modifiers, self.function_name_start_position).single_line.strip()
563
564     def parameter_list(self):
565         if not self._parameter_list:
566             # Store the final result as a tuple since that is immutable.
567             self._parameter_list = tuple(parameter_list(self._clean_lines.elided, self.parameter_start_position, self.parameter_end_position))
568
569         return self._parameter_list
570
571     def count(self, line_number):
572         """Count line in current function body."""
573         if self.in_a_function and line_number >= self.body_start_position.row:
574             self.lines_in_function += 1
575
576     def check(self, error, line_number):
577         """Report if too many lines in function body.
578
579         Args:
580           error: The function to call with any errors found.
581           line_number: The number of the line to check.
582         """
583         if match(r'T(EST|est)', self.current_function):
584             base_trigger = self._TEST_TRIGGER
585         else:
586             base_trigger = self._NORMAL_TRIGGER
587         trigger = base_trigger * 2 ** self.min_confidence
588
589         if self.lines_in_function > trigger:
590             error_level = int(math.log(self.lines_in_function / base_trigger, 2))
591             # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ...
592             if error_level > 5:
593                 error_level = 5
594             error(line_number, 'readability/fn_size', error_level,
595                   'Small and focused functions are preferred:'
596                   ' %s has %d non-comment lines'
597                   ' (error triggered by exceeding %d lines).'  % (
598                       self.current_function, self.lines_in_function, trigger))
599
600     def end(self):
601         """Stop analyzing function body."""
602         self.in_a_function = False
603
604
605 class _IncludeError(Exception):
606     """Indicates a problem with the include order in a file."""
607     pass
608
609
610 class FileInfo:
611     """Provides utility functions for filenames.
612
613     FileInfo provides easy access to the components of a file's path
614     relative to the project root.
615     """
616
617     def __init__(self, filename):
618         self._filename = filename
619
620     def full_name(self):
621         """Make Windows paths like Unix."""
622         return os.path.abspath(self._filename).replace('\\', '/')
623
624     def repository_name(self):
625         """Full name after removing the local path to the repository.
626
627         If we have a real absolute path name here we can try to do something smart:
628         detecting the root of the checkout and truncating /path/to/checkout from
629         the name so that we get header guards that don't include things like
630         "C:\Documents and Settings\..." or "/home/username/..." in them and thus
631         people on different computers who have checked the source out to different
632         locations won't see bogus errors.
633         """
634         fullname = self.full_name()
635
636         if os.path.exists(fullname):
637             project_dir = os.path.dirname(fullname)
638
639             if os.path.exists(os.path.join(project_dir, ".svn")):
640                 # If there's a .svn file in the current directory, we
641                 # recursively look up the directory tree for the top
642                 # of the SVN checkout
643                 root_dir = project_dir
644                 one_up_dir = os.path.dirname(root_dir)
645                 while os.path.exists(os.path.join(one_up_dir, ".svn")):
646                     root_dir = os.path.dirname(root_dir)
647                     one_up_dir = os.path.dirname(one_up_dir)
648
649                 prefix = os.path.commonprefix([root_dir, project_dir])
650                 return fullname[len(prefix) + 1:]
651
652             # Not SVN? Try to find a git top level directory by
653             # searching up from the current path.
654             root_dir = os.path.dirname(fullname)
655             while (root_dir != os.path.dirname(root_dir)
656                    and not os.path.exists(os.path.join(root_dir, ".git"))):
657                 root_dir = os.path.dirname(root_dir)
658                 if os.path.exists(os.path.join(root_dir, ".git")):
659                     prefix = os.path.commonprefix([root_dir, project_dir])
660                     return fullname[len(prefix) + 1:]
661
662         # Don't know what to do; header guard warnings may be wrong...
663         return fullname
664
665     def split(self):
666         """Splits the file into the directory, basename, and extension.
667
668         For 'chrome/browser/browser.cpp', Split() would
669         return ('chrome/browser', 'browser', '.cpp')
670
671         Returns:
672           A tuple of (directory, basename, extension).
673         """
674
675         googlename = self.repository_name()
676         project, rest = os.path.split(googlename)
677         return (project,) + os.path.splitext(rest)
678
679     def base_name(self):
680         """File base name - text after the final slash, before the final period."""
681         return self.split()[1]
682
683     def extension(self):
684         """File extension - text following the final period."""
685         return self.split()[2]
686
687     def no_extension(self):
688         """File has no source file extension."""
689         return '/'.join(self.split()[0:2])
690
691     def is_source(self):
692         """File has a source file extension."""
693         return self.extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
694
695
696 # Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard.
697 _RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile(
698     r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)')
699 # Matches strings.  Escape codes should already be removed by ESCAPES.
700 _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"')
701 # Matches characters.  Escape codes should already be removed by ESCAPES.
702 _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'")
703 # Matches multi-line C++ comments.
704 # This RE is a little bit more complicated than one might expect, because we
705 # have to take care of space removals tools so we can handle comments inside
706 # statements better.
707 # The current rule is: We only clear spaces from both sides when we're at the
708 # end of the line. Otherwise, we try to remove spaces from the right side,
709 # if this doesn't work we try on left side but only if there's a non-character
710 # on the right.
711 _RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile(
712     r"""(\s*/\*.*\*/\s*$|
713             /\*.*\*/\s+|
714          \s+/\*.*\*/(?=\W)|
715             /\*.*\*/)""", re.VERBOSE)
716
717
718 def is_cpp_string(line):
719     """Does line terminate so, that the next symbol is in string constant.
720
721     This function does not consider single-line nor multi-line comments.
722
723     Args:
724       line: is a partial line of code starting from the 0..n.
725
726     Returns:
727       True, if next character appended to 'line' is inside a
728       string constant.
729     """
730
731     line = line.replace(r'\\', 'XX')  # after this, \\" does not match to \"
732     return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
733
734
735 def find_next_multi_line_comment_start(lines, line_index):
736     """Find the beginning marker for a multiline comment."""
737     while line_index < len(lines):
738         if lines[line_index].strip().startswith('/*'):
739             # Only return this marker if the comment goes beyond this line
740             if lines[line_index].strip().find('*/', 2) < 0:
741                 return line_index
742         line_index += 1
743     return len(lines)
744
745
746 def find_next_multi_line_comment_end(lines, line_index):
747     """We are inside a comment, find the end marker."""
748     while line_index < len(lines):
749         if lines[line_index].strip().endswith('*/'):
750             return line_index
751         line_index += 1
752     return len(lines)
753
754
755 def remove_multi_line_comments_from_range(lines, begin, end):
756     """Clears a range of lines for multi-line comments."""
757     # Having // dummy comments makes the lines non-empty, so we will not get
758     # unnecessary blank line warnings later in the code.
759     for i in range(begin, end):
760         lines[i] = '// dummy'
761
762
763 def remove_multi_line_comments(lines, error):
764     """Removes multiline (c-style) comments from lines."""
765     line_index = 0
766     while line_index < len(lines):
767         line_index_begin = find_next_multi_line_comment_start(lines, line_index)
768         if line_index_begin >= len(lines):
769             return
770         line_index_end = find_next_multi_line_comment_end(lines, line_index_begin)
771         if line_index_end >= len(lines):
772             error(line_index_begin + 1, 'readability/multiline_comment', 5,
773                   'Could not find end of multi-line comment')
774             return
775         remove_multi_line_comments_from_range(lines, line_index_begin, line_index_end + 1)
776         line_index = line_index_end + 1
777
778
779 def cleanse_comments(line):
780     """Removes //-comments and single-line C-style /* */ comments.
781
782     Args:
783       line: A line of C++ source.
784
785     Returns:
786       The line with single-line comments removed.
787     """
788     comment_position = line.find('//')
789     if comment_position != -1 and not is_cpp_string(line[:comment_position]):
790         line = line[:comment_position]
791     # get rid of /* ... */
792     return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line)
793
794
795 class CleansedLines(object):
796     """Holds 3 copies of all lines with different preprocessing applied to them.
797
798     1) elided member contains lines without strings and comments,
799     2) lines member contains lines without comments, and
800     3) raw member contains all the lines without processing.
801     All these three members are of <type 'list'>, and of the same length.
802     """
803
804     def __init__(self, lines):
805         self.elided = []
806         self.lines = []
807         self.raw_lines = lines
808         self._num_lines = len(lines)
809         for line_number in range(len(lines)):
810             self.lines.append(cleanse_comments(lines[line_number]))
811             elided = self.collapse_strings(lines[line_number])
812             self.elided.append(cleanse_comments(elided))
813
814     def num_lines(self):
815         """Returns the number of lines represented."""
816         return self._num_lines
817
818     @staticmethod
819     def collapse_strings(elided):
820         """Collapses strings and chars on a line to simple "" or '' blocks.
821
822         We nix strings first so we're not fooled by text like '"http://"'
823
824         Args:
825           elided: The line being processed.
826
827         Returns:
828           The line with collapsed strings.
829         """
830         if not _RE_PATTERN_INCLUDE.match(elided):
831             # Remove escaped characters first to make quote/single quote collapsing
832             # basic.  Things that look like escaped characters shouldn't occur
833             # outside of strings and chars.
834             elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided)
835             elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided)
836             elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided)
837         return elided
838
839
840 def close_expression(elided, position):
841     """If input points to ( or { or [, finds the position that closes it.
842
843     If elided[position.row][position.column] points to a '(' or '{' or '[',
844     finds the line_number/pos that correspond to the closing of the expression.
845
846      Args:
847        elided: A CleansedLines.elided instance containing the file.
848        position: The position of the opening item.
849
850      Returns:
851       The Position *past* the closing brace, or Position(len(elided), -1)
852       if we never find a close. Note we ignore strings and comments when matching.
853     """
854     line = elided[position.row]
855     start_character = line[position.column]
856     if start_character == '(':
857         enclosing_character_regex = r'[\(\)]'
858     elif start_character == '[':
859         enclosing_character_regex = r'[\[\]]'
860     elif start_character == '{':
861         enclosing_character_regex = r'[\{\}]'
862     else:
863         return Position(len(elided), -1)
864
865     current_column = position.column + 1
866     line_number = position.row
867     net_open = 1
868     for line in elided[position.row:]:
869         line = line[current_column:]
870
871         # Search the current line for opening and closing characters.
872         while True:
873             next_enclosing_character = search(enclosing_character_regex, line)
874             # No more on this line.
875             if not next_enclosing_character:
876                 break
877             current_column += next_enclosing_character.end(0)
878             line = line[next_enclosing_character.end(0):]
879             if next_enclosing_character.group(0) == start_character:
880                 net_open += 1
881             else:
882                 net_open -= 1
883                 if not net_open:
884                     return Position(line_number, current_column)
885
886         # Proceed to the next line.
887         line_number += 1
888         current_column = 0
889
890     # The given item was not closed.
891     return Position(len(elided), -1)
892
893 def check_for_copyright(lines, error):
894     """Logs an error if no Copyright message appears at the top of the file."""
895
896     # We'll say it should occur by line 10. Don't forget there's a
897     # dummy line at the front.
898     for line in xrange(1, min(len(lines), 11)):
899         if re.search(r'Copyright', lines[line], re.I):
900             break
901     else:                       # means no copyright line was found
902         error(0, 'legal/copyright', 5,
903               'No copyright message found.  '
904               'You should have a line: "Copyright [year] <Copyright Owner>"')
905
906
907 def get_header_guard_cpp_variable(filename):
908     """Returns the CPP variable that should be used as a header guard.
909
910     Args:
911       filename: The name of a C++ header file.
912
913     Returns:
914       The CPP variable that should be used as a header guard in the
915       named file.
916
917     """
918
919     # Restores original filename in case that style checker is invoked from Emacs's
920     # flymake.
921     filename = re.sub(r'_flymake\.h$', '.h', filename)
922
923     standard_name = sub(r'[-.\s]', '_', os.path.basename(filename))
924
925     # Files under WTF typically have header guards that start with WTF_.
926     if filename.find('/wtf/'):
927         special_name = "WTF_" + standard_name
928     else:
929         special_name = standard_name
930     return (special_name, standard_name)
931
932
933 def check_for_header_guard(filename, lines, error):
934     """Checks that the file contains a header guard.
935
936     Logs an error if no #ifndef header guard is present.  For other
937     headers, checks that the full pathname is used.
938
939     Args:
940       filename: The name of the C++ header file.
941       lines: An array of strings, each representing a line of the file.
942       error: The function to call with any errors found.
943     """
944
945     cppvar = get_header_guard_cpp_variable(filename)
946
947     ifndef = None
948     ifndef_line_number = 0
949     define = None
950     for line_number, line in enumerate(lines):
951         line_split = line.split()
952         if len(line_split) >= 2:
953             # find the first occurrence of #ifndef and #define, save arg
954             if not ifndef and line_split[0] == '#ifndef':
955                 # set ifndef to the header guard presented on the #ifndef line.
956                 ifndef = line_split[1]
957                 ifndef_line_number = line_number
958             if not define and line_split[0] == '#define':
959                 define = line_split[1]
960             if define and ifndef:
961                 break
962
963     if not ifndef or not define or ifndef != define:
964         error(0, 'build/header_guard', 5,
965               'No #ifndef header guard found, suggested CPP variable is: %s' %
966               cppvar[0])
967         return
968
969     # The guard should be File_h.
970     if ifndef not in cppvar:
971         error(ifndef_line_number, 'build/header_guard', 5,
972               '#ifndef header guard has wrong style, please use: %s' % cppvar[0])
973
974
975 def check_for_unicode_replacement_characters(lines, error):
976     """Logs an error for each line containing Unicode replacement characters.
977
978     These indicate that either the file contained invalid UTF-8 (likely)
979     or Unicode replacement characters (which it shouldn't).  Note that
980     it's possible for this to throw off line numbering if the invalid
981     UTF-8 occurred adjacent to a newline.
982
983     Args:
984       lines: An array of strings, each representing a line of the file.
985       error: The function to call with any errors found.
986     """
987     for line_number, line in enumerate(lines):
988         if u'\ufffd' in line:
989             error(line_number, 'readability/utf8', 5,
990                   'Line contains invalid UTF-8 (or Unicode replacement character).')
991
992
993 def check_for_new_line_at_eof(lines, error):
994     """Logs an error if there is no newline char at the end of the file.
995
996     Args:
997       lines: An array of strings, each representing a line of the file.
998       error: The function to call with any errors found.
999     """
1000
1001     # The array lines() was created by adding two newlines to the
1002     # original file (go figure), then splitting on \n.
1003     # To verify that the file ends in \n, we just have to make sure the
1004     # last-but-two element of lines() exists and is empty.
1005     if len(lines) < 3 or lines[-2]:
1006         error(len(lines) - 2, 'whitespace/ending_newline', 5,
1007               'Could not find a newline character at the end of the file.')
1008
1009
1010 def check_for_multiline_comments_and_strings(clean_lines, line_number, error):
1011     """Logs an error if we see /* ... */ or "..." that extend past one line.
1012
1013     /* ... */ comments are legit inside macros, for one line.
1014     Otherwise, we prefer // comments, so it's ok to warn about the
1015     other.  Likewise, it's ok for strings to extend across multiple
1016     lines, as long as a line continuation character (backslash)
1017     terminates each line. Although not currently prohibited by the C++
1018     style guide, it's ugly and unnecessary. We don't do well with either
1019     in this lint program, so we warn about both.
1020
1021     Args:
1022       clean_lines: A CleansedLines instance containing the file.
1023       line_number: The number of the line to check.
1024       error: The function to call with any errors found.
1025     """
1026     line = clean_lines.elided[line_number]
1027
1028     # Remove all \\ (escaped backslashes) from the line. They are OK, and the
1029     # second (escaped) slash may trigger later \" detection erroneously.
1030     line = line.replace('\\\\', '')
1031
1032     if line.count('/*') > line.count('*/'):
1033         error(line_number, 'readability/multiline_comment', 5,
1034               'Complex multi-line /*...*/-style comment found. '
1035               'Lint may give bogus warnings.  '
1036               'Consider replacing these with //-style comments, '
1037               'with #if 0...#endif, '
1038               'or with more clearly structured multi-line comments.')
1039
1040     if (line.count('"') - line.count('\\"')) % 2:
1041         error(line_number, 'readability/multiline_string', 5,
1042               'Multi-line string ("...") found.  This lint script doesn\'t '
1043               'do well with such strings, and may give bogus warnings.  They\'re '
1044               'ugly and unnecessary, and you should use concatenation instead".')
1045
1046
1047 _THREADING_LIST = (
1048     ('asctime(', 'asctime_r('),
1049     ('ctime(', 'ctime_r('),
1050     ('getgrgid(', 'getgrgid_r('),
1051     ('getgrnam(', 'getgrnam_r('),
1052     ('getlogin(', 'getlogin_r('),
1053     ('getpwnam(', 'getpwnam_r('),
1054     ('getpwuid(', 'getpwuid_r('),
1055     ('gmtime(', 'gmtime_r('),
1056     ('localtime(', 'localtime_r('),
1057     ('rand(', 'rand_r('),
1058     ('readdir(', 'readdir_r('),
1059     ('strtok(', 'strtok_r('),
1060     ('ttyname(', 'ttyname_r('),
1061     )
1062
1063
1064 def check_posix_threading(clean_lines, line_number, error):
1065     """Checks for calls to thread-unsafe functions.
1066
1067     Much code has been originally written without consideration of
1068     multi-threading. Also, engineers are relying on their old experience;
1069     they have learned posix before threading extensions were added. These
1070     tests guide the engineers to use thread-safe functions (when using
1071     posix directly).
1072
1073     Args:
1074       clean_lines: A CleansedLines instance containing the file.
1075       line_number: The number of the line to check.
1076       error: The function to call with any errors found.
1077     """
1078     line = clean_lines.elided[line_number]
1079     for single_thread_function, multithread_safe_function in _THREADING_LIST:
1080         index = line.find(single_thread_function)
1081         # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
1082         if index >= 0 and (index == 0 or (not line[index - 1].isalnum()
1083                                           and line[index - 1] not in ('_', '.', '>'))):
1084             error(line_number, 'runtime/threadsafe_fn', 2,
1085                   'Consider using ' + multithread_safe_function +
1086                   '...) instead of ' + single_thread_function +
1087                   '...) for improved thread safety.')
1088
1089
1090 # Matches invalid increment: *count++, which moves pointer instead of
1091 # incrementing a value.
1092 _RE_PATTERN_INVALID_INCREMENT = re.compile(
1093     r'^\s*\*\w+(\+\+|--);')
1094
1095
1096 def check_invalid_increment(clean_lines, line_number, error):
1097     """Checks for invalid increment *count++.
1098
1099     For example following function:
1100     void increment_counter(int* count) {
1101         *count++;
1102     }
1103     is invalid, because it effectively does count++, moving pointer, and should
1104     be replaced with ++*count, (*count)++ or *count += 1.
1105
1106     Args:
1107       clean_lines: A CleansedLines instance containing the file.
1108       line_number: The number of the line to check.
1109       error: The function to call with any errors found.
1110     """
1111     line = clean_lines.elided[line_number]
1112     if _RE_PATTERN_INVALID_INCREMENT.match(line):
1113         error(line_number, 'runtime/invalid_increment', 5,
1114               'Changing pointer instead of value (or unused value of operator*).')
1115
1116
1117 class _ClassInfo(object):
1118     """Stores information about a class."""
1119
1120     def __init__(self, name, line_number):
1121         self.name = name
1122         self.line_number = line_number
1123         self.seen_open_brace = False
1124         self.is_derived = False
1125         self.virtual_method_line_number = None
1126         self.has_virtual_destructor = False
1127         self.brace_depth = 0
1128
1129
1130 class _ClassState(object):
1131     """Holds the current state of the parse relating to class declarations.
1132
1133     It maintains a stack of _ClassInfos representing the parser's guess
1134     as to the current nesting of class declarations. The innermost class
1135     is at the top (back) of the stack. Typically, the stack will either
1136     be empty or have exactly one entry.
1137     """
1138
1139     def __init__(self):
1140         self.classinfo_stack = []
1141
1142     def check_finished(self, error):
1143         """Checks that all classes have been completely parsed.
1144
1145         Call this when all lines in a file have been processed.
1146         Args:
1147           error: The function to call with any errors found.
1148         """
1149         if self.classinfo_stack:
1150             # Note: This test can result in false positives if #ifdef constructs
1151             # get in the way of brace matching. See the testBuildClass test in
1152             # cpp_style_unittest.py for an example of this.
1153             error(self.classinfo_stack[0].line_number, 'build/class', 5,
1154                   'Failed to find complete declaration of class %s' %
1155                   self.classinfo_stack[0].name)
1156
1157
1158 class _FileState(object):
1159     def __init__(self, clean_lines, file_extension):
1160         self._did_inside_namespace_indent_warning = False
1161         self._clean_lines = clean_lines
1162         if file_extension in ['m', 'mm']:
1163             self._is_objective_c = True
1164         elif file_extension == 'h':
1165             # In the case of header files, it is unknown if the file
1166             # is objective c or not, so set this value to None and then
1167             # if it is requested, use heuristics to guess the value.
1168             self._is_objective_c = None
1169         else:
1170             self._is_objective_c = False
1171         self._is_c = file_extension == 'c'
1172
1173     def set_did_inside_namespace_indent_warning(self):
1174         self._did_inside_namespace_indent_warning = True
1175
1176     def did_inside_namespace_indent_warning(self):
1177         return self._did_inside_namespace_indent_warning
1178
1179     def is_objective_c(self):
1180         if self._is_objective_c is None:
1181             for line in self._clean_lines.elided:
1182                 # Starting with @ or #import seem like the best indications
1183                 # that we have an Objective C file.
1184                 if line.startswith("@") or line.startswith("#import"):
1185                     self._is_objective_c = True
1186                     break
1187             else:
1188                 self._is_objective_c = False
1189         return self._is_objective_c
1190
1191     def is_c_or_objective_c(self):
1192         """Return whether the file extension corresponds to C or Objective-C."""
1193         return self._is_c or self.is_objective_c()
1194
1195
1196 def check_for_non_standard_constructs(clean_lines, line_number,
1197                                       class_state, error):
1198     """Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
1199
1200     Complain about several constructs which gcc-2 accepts, but which are
1201     not standard C++.  Warning about these in lint is one way to ease the
1202     transition to new compilers.
1203     - put storage class first (e.g. "static const" instead of "const static").
1204     - "%lld" instead of %qd" in printf-type functions.
1205     - "%1$d" is non-standard in printf-type functions.
1206     - "\%" is an undefined character escape sequence.
1207     - text after #endif is not allowed.
1208     - invalid inner-style forward declaration.
1209     - >? and <? operators, and their >?= and <?= cousins.
1210     - classes with virtual methods need virtual destructors (compiler warning
1211         available, but not turned on yet.)
1212
1213     Additionally, check for constructor/destructor style violations as it
1214     is very convenient to do so while checking for gcc-2 compliance.
1215
1216     Args:
1217       clean_lines: A CleansedLines instance containing the file.
1218       line_number: The number of the line to check.
1219       class_state: A _ClassState instance which maintains information about
1220                    the current stack of nested class declarations being parsed.
1221       error: A callable to which errors are reported, which takes parameters:
1222              line number, error level, and message
1223     """
1224
1225     # Remove comments from the line, but leave in strings for now.
1226     line = clean_lines.lines[line_number]
1227
1228     if search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
1229         error(line_number, 'runtime/printf_format', 3,
1230               '%q in format strings is deprecated.  Use %ll instead.')
1231
1232     if search(r'printf\s*\(.*".*%\d+\$', line):
1233         error(line_number, 'runtime/printf_format', 2,
1234               '%N$ formats are unconventional.  Try rewriting to avoid them.')
1235
1236     # Remove escaped backslashes before looking for undefined escapes.
1237     line = line.replace('\\\\', '')
1238
1239     if search(r'("|\').*\\(%|\[|\(|{)', line):
1240         error(line_number, 'build/printf_format', 3,
1241               '%, [, (, and { are undefined character escapes.  Unescape them.')
1242
1243     # For the rest, work with both comments and strings removed.
1244     line = clean_lines.elided[line_number]
1245
1246     if search(r'\b(const|volatile|void|char|short|int|long'
1247               r'|float|double|signed|unsigned'
1248               r'|schar|u?int8|u?int16|u?int32|u?int64)'
1249               r'\s+(auto|register|static|extern|typedef)\b',
1250               line):
1251         error(line_number, 'build/storage_class', 5,
1252               'Storage class (static, extern, typedef, etc) should be first.')
1253
1254     if match(r'\s*#\s*endif\s*[^/\s]+', line):
1255         error(line_number, 'build/endif_comment', 5,
1256               'Uncommented text after #endif is non-standard.  Use a comment.')
1257
1258     if match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
1259         error(line_number, 'build/forward_decl', 5,
1260               'Inner-style forward declarations are invalid.  Remove this line.')
1261
1262     if search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', line):
1263         error(line_number, 'build/deprecated', 3,
1264               '>? and <? (max and min) operators are non-standard and deprecated.')
1265
1266     # Track class entry and exit, and attempt to find cases within the
1267     # class declaration that don't meet the C++ style
1268     # guidelines. Tracking is very dependent on the code matching Google
1269     # style guidelines, but it seems to perform well enough in testing
1270     # to be a worthwhile addition to the checks.
1271     classinfo_stack = class_state.classinfo_stack
1272     # Look for a class declaration
1273     class_decl_match = match(
1274         r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line)
1275     if class_decl_match:
1276         classinfo_stack.append(_ClassInfo(class_decl_match.group(3), line_number))
1277
1278     # Everything else in this function uses the top of the stack if it's
1279     # not empty.
1280     if not classinfo_stack:
1281         return
1282
1283     classinfo = classinfo_stack[-1]
1284
1285     # If the opening brace hasn't been seen look for it and also
1286     # parent class declarations.
1287     if not classinfo.seen_open_brace:
1288         # If the line has a ';' in it, assume it's a forward declaration or
1289         # a single-line class declaration, which we won't process.
1290         if line.find(';') != -1:
1291             classinfo_stack.pop()
1292             return
1293         classinfo.seen_open_brace = (line.find('{') != -1)
1294         # Look for a bare ':'
1295         if search('(^|[^:]):($|[^:])', line):
1296             classinfo.is_derived = True
1297         if not classinfo.seen_open_brace:
1298             return  # Everything else in this function is for after open brace
1299
1300     # The class may have been declared with namespace or classname qualifiers.
1301     # The constructor and destructor will not have those qualifiers.
1302     base_classname = classinfo.name.split('::')[-1]
1303
1304     # Look for single-argument constructors that aren't marked explicit.
1305     # Technically a valid construct, but against style.
1306     args = match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)'
1307                  % re.escape(base_classname),
1308                  line)
1309     if (args
1310         and args.group(1) != 'void'
1311         and not match(r'(const\s+)?%s\s*&' % re.escape(base_classname),
1312                       args.group(1).strip())):
1313         error(line_number, 'runtime/explicit', 5,
1314               'Single-argument constructors should be marked explicit.')
1315
1316     # Look for methods declared virtual.
1317     if search(r'\bvirtual\b', line):
1318         classinfo.virtual_method_line_number = line_number
1319         # Only look for a destructor declaration on the same line. It would
1320         # be extremely unlikely for the destructor declaration to occupy
1321         # more than one line.
1322         if search(r'~%s\s*\(' % base_classname, line):
1323             classinfo.has_virtual_destructor = True
1324
1325     # Look for class end.
1326     brace_depth = classinfo.brace_depth
1327     brace_depth = brace_depth + line.count('{') - line.count('}')
1328     if brace_depth <= 0:
1329         classinfo = classinfo_stack.pop()
1330         # Try to detect missing virtual destructor declarations.
1331         # For now, only warn if a non-derived class with virtual methods lacks
1332         # a virtual destructor. This is to make it less likely that people will
1333         # declare derived virtual destructors without declaring the base
1334         # destructor virtual.
1335         if ((classinfo.virtual_method_line_number is not None)
1336             and (not classinfo.has_virtual_destructor)
1337             and (not classinfo.is_derived)):  # Only warn for base classes
1338             error(classinfo.line_number, 'runtime/virtual', 4,
1339                   'The class %s probably needs a virtual destructor due to '
1340                   'having virtual method(s), one declared at line %d.'
1341                   % (classinfo.name, classinfo.virtual_method_line_number))
1342     else:
1343         classinfo.brace_depth = brace_depth
1344
1345
1346 def check_spacing_for_function_call(line, line_number, error):
1347     """Checks for the correctness of various spacing around function calls.
1348
1349     Args:
1350       line: The text of the line to check.
1351       line_number: The number of the line to check.
1352       error: The function to call with any errors found.
1353     """
1354
1355     # Since function calls often occur inside if/for/foreach/while/switch
1356     # expressions - which have their own, more liberal conventions - we
1357     # first see if we should be looking inside such an expression for a
1358     # function call, to which we can apply more strict standards.
1359     function_call = line    # if there's no control flow construct, look at whole line
1360     for pattern in (r'\bif\s*\((.*)\)\s*{',
1361                     r'\bfor\s*\((.*)\)\s*{',
1362                     r'\bforeach\s*\((.*)\)\s*{',
1363                     r'\bwhile\s*\((.*)\)\s*[{;]',
1364                     r'\bswitch\s*\((.*)\)\s*{'):
1365         matched = search(pattern, line)
1366         if matched:
1367             function_call = matched.group(1)    # look inside the parens for function calls
1368             break
1369
1370     # Except in if/for/foreach/while/switch, there should never be space
1371     # immediately inside parens (eg "f( 3, 4 )").  We make an exception
1372     # for nested parens ( (a+b) + c ).  Likewise, there should never be
1373     # a space before a ( when it's a function argument.  I assume it's a
1374     # function argument when the char before the whitespace is legal in
1375     # a function name (alnum + _) and we're not starting a macro. Also ignore
1376     # pointers and references to arrays and functions coz they're too tricky:
1377     # we use a very simple way to recognize these:
1378     # " (something)(maybe-something)" or
1379     # " (something)(maybe-something," or
1380     # " (something)[something]"
1381     # Note that we assume the contents of [] to be short enough that
1382     # they'll never need to wrap.
1383     if (  # Ignore control structures.
1384         not search(r'\b(if|for|foreach|while|switch|return|new|delete)\b', function_call)
1385         # Ignore pointers/references to functions.
1386         and not search(r' \([^)]+\)\([^)]*(\)|,$)', function_call)
1387         # Ignore pointers/references to arrays.
1388         and not search(r' \([^)]+\)\[[^\]]+\]', function_call)):
1389         if search(r'\w\s*\([ \t](?!\s*\\$)', function_call):      # a ( used for a fn call
1390             error(line_number, 'whitespace/parens', 4,
1391                   'Extra space after ( in function call')
1392         elif search(r'\([ \t]+(?!(\s*\\)|\()', function_call):
1393             error(line_number, 'whitespace/parens', 2,
1394                   'Extra space after (')
1395         if (search(r'\w\s+\(', function_call)
1396             and not match(r'\s*(#|typedef)', function_call)):
1397             error(line_number, 'whitespace/parens', 4,
1398                   'Extra space before ( in function call')
1399         # If the ) is followed only by a newline or a { + newline, assume it's
1400         # part of a control statement (if/while/etc), and don't complain
1401         if search(r'[^)\s]\s+\)(?!\s*$|{\s*$)', function_call):
1402             error(line_number, 'whitespace/parens', 2,
1403                   'Extra space before )')
1404
1405
1406 def is_blank_line(line):
1407     """Returns true if the given line is blank.
1408
1409     We consider a line to be blank if the line is empty or consists of
1410     only white spaces.
1411
1412     Args:
1413       line: A line of a string.
1414
1415     Returns:
1416       True, if the given line is blank.
1417     """
1418     return not line or line.isspace()
1419
1420
1421 def detect_functions(clean_lines, line_number, function_state, error):
1422     """Finds where functions start and end.
1423
1424     Uses a simplistic algorithm assuming other style guidelines
1425     (especially spacing) are followed.
1426     Trivial bodies are unchecked, so constructors with huge initializer lists
1427     may be missed.
1428
1429     Args:
1430       clean_lines: A CleansedLines instance containing the file.
1431       line_number: The number of the line to check.
1432       function_state: Current function name and lines in body so far.
1433       error: The function to call with any errors found.
1434     """
1435     # Are we now past the end of a function?
1436     if function_state.end_position.row + 1 == line_number:
1437         function_state.end()
1438
1439     # If we're in a function, don't try to detect a new one.
1440     if function_state.in_a_function:
1441         return
1442
1443     lines = clean_lines.lines
1444     line = lines[line_number]
1445     raw = clean_lines.raw_lines
1446     raw_line = raw[line_number]
1447
1448     # Lines ending with a \ indicate a macro. Don't try to check them.
1449     if raw_line.endswith('\\'):
1450         return
1451
1452     regexp = r'\s*(\w(\w|::|\*|\&|\s|<|>|,|~|(operator\s*(/|-|=|!|\+)+))*)\('  # decls * & space::name( ...
1453     match_result = match(regexp, line)
1454     if not match_result:
1455         return
1456
1457     # If the name is all caps and underscores, figure it's a macro and
1458     # ignore it, unless it's TEST or TEST_F.
1459     function_name = match_result.group(1).split()[-1]
1460     if function_name != 'TEST' and function_name != 'TEST_F' and match(r'[A-Z_]+$', function_name):
1461         return
1462
1463     joined_line = ''
1464     for start_line_number in xrange(line_number, clean_lines.num_lines()):
1465         start_line = clean_lines.elided[start_line_number]
1466         joined_line += ' ' + start_line.lstrip()
1467         body_match = search(r'{|;', start_line)
1468         if body_match:
1469             body_start_position = Position(start_line_number, body_match.start(0))
1470
1471             # Replace template constructs with _ so that no spaces remain in the function name,
1472             # while keeping the column numbers of other characters the same as "line".
1473             line_with_no_templates = iteratively_replace_matches_with_char(r'<[^<>]*>', '_', line)
1474             match_function = search(r'((\w|:|<|>|,|~|(operator\s*(/|-|=|!|\+)+))*)\(', line_with_no_templates)
1475             if not match_function:
1476                 return  # The '(' must have been inside of a template.
1477
1478             # Use the column numbers from the modified line to find the
1479             # function name in the original line.
1480             function = line[match_function.start(1):match_function.end(1)]
1481             function_name_start_position = Position(line_number, match_function.start(1))
1482
1483             if match(r'TEST', function):    # Handle TEST... macros
1484                 parameter_regexp = search(r'(\(.*\))', joined_line)
1485                 if parameter_regexp:             # Ignore bad syntax
1486                     function += parameter_regexp.group(1)
1487             else:
1488                 function += '()'
1489
1490             parameter_start_position = Position(line_number, match_function.end(1))
1491             parameter_end_position = close_expression(clean_lines.elided, parameter_start_position)
1492             if parameter_end_position.row == len(clean_lines.elided):
1493                 # No end was found.
1494                 return
1495
1496             if start_line[body_start_position.column] == ';':
1497                 end_position = Position(body_start_position.row, body_start_position.column + 1)
1498             else:
1499                 end_position = close_expression(clean_lines.elided, body_start_position)
1500
1501             # Check for nonsensical positions. (This happens in test cases which check code snippets.)
1502             if parameter_end_position > body_start_position:
1503                 return
1504
1505             function_state.begin(function, function_name_start_position, body_start_position, end_position,
1506                                  parameter_start_position, parameter_end_position, clean_lines)
1507             return
1508
1509     # No body for the function (or evidence of a non-function) was found.
1510     error(line_number, 'readability/fn_size', 5,
1511           'Lint failed to find start of function body.')
1512
1513
1514 def check_for_function_lengths(clean_lines, line_number, function_state, error):
1515     """Reports for long function bodies.
1516
1517     For an overview why this is done, see:
1518     http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
1519
1520     Blank/comment lines are not counted so as to avoid encouraging the removal
1521     of vertical space and commments just to get through a lint check.
1522     NOLINT *on the last line of a function* disables this check.
1523
1524     Args:
1525       clean_lines: A CleansedLines instance containing the file.
1526       line_number: The number of the line to check.
1527       function_state: Current function name and lines in body so far.
1528       error: The function to call with any errors found.
1529     """
1530     lines = clean_lines.lines
1531     line = lines[line_number]
1532     raw = clean_lines.raw_lines
1533     raw_line = raw[line_number]
1534
1535     if function_state.end_position.row == line_number:  # last line
1536         if not search(r'\bNOLINT\b', raw_line):
1537             function_state.check(error, line_number)
1538     elif not match(r'^\s*$', line):
1539         function_state.count(line_number)  # Count non-blank/non-comment lines.
1540
1541
1542 def _check_parameter_name_against_text(parameter, text, error):
1543     """Checks to see if the parameter name is contained within the text.
1544
1545     Return false if the check failed (i.e. an error was produced).
1546     """
1547
1548     # Treat 'lower with underscores' as a canonical form because it is
1549     # case insensitive while still retaining word breaks. (This ensures that
1550     # 'elate' doesn't look like it is duplicating of 'NateLate'.)
1551     canonical_parameter_name = parameter.lower_with_underscores_name()
1552
1553     # Appends "object" to all text to catch variables that did the same (but only
1554     # do this when the parameter name is more than a single character to avoid
1555     # flagging 'b' which may be an ok variable when used in an rgba function).
1556     if len(canonical_parameter_name) > 1:
1557         text = sub(r'(\w)\b', r'\1Object', text)
1558     canonical_text = _convert_to_lower_with_underscores(text)
1559
1560     # Used to detect cases like ec for ExceptionCode.
1561     acronym = _create_acronym(text).lower()
1562     if canonical_text.find(canonical_parameter_name) != -1 or acronym.find(canonical_parameter_name) != -1:
1563         error(parameter.row, 'readability/parameter_name', 5,
1564               'The parameter name "%s" adds no information, so it should be removed.' % parameter.name)
1565         return False
1566     return True
1567
1568
1569 def check_function_definition(filename, file_extension, clean_lines, line_number, function_state, error):
1570     """Check that function definitions for style issues.
1571
1572     Specifically, check that parameter names in declarations add information.
1573
1574     Args:
1575        filename: Filename of the file that is being processed.
1576        file_extension: The current file extension, without the leading dot.
1577        clean_lines: A CleansedLines instance containing the file.
1578        line_number: The number of the line to check.
1579        function_state: Current function name and lines in body so far.
1580        error: The function to call with any errors found.
1581     """
1582     if line_number != function_state.body_start_position.row:
1583         return
1584
1585     modifiers_and_return_type = function_state.modifiers_and_return_type()
1586     if filename.find('/chromium/') != -1 and search(r'\bWEBKIT_API\b', modifiers_and_return_type):
1587         if filename.find('/chromium/public/') == -1:
1588             error(function_state.function_name_start_position.row, 'readability/webkit_api', 5,
1589                   'WEBKIT_API should only appear in the chromium public directory.')
1590         elif not file_extension == "h":
1591             error(function_state.function_name_start_position.row, 'readability/webkit_api', 5,
1592                   'WEBKIT_API should only be used in header files.')
1593         elif not function_state.is_declaration or search(r'\binline\b', modifiers_and_return_type):
1594             error(function_state.function_name_start_position.row, 'readability/webkit_api', 5,
1595                   'WEBKIT_API should not be used on a function with a body.')
1596         elif function_state.is_pure:
1597             error(function_state.function_name_start_position.row, 'readability/webkit_api', 5,
1598                   'WEBKIT_API should not be used with a pure virtual function.')
1599
1600     parameter_list = function_state.parameter_list()
1601     for parameter in parameter_list:
1602         bad_parameter_type = search('(?=\W|^)(Ref|Own)Ptr(?=\W)', parameter.type)
1603         if bad_parameter_type:
1604             type_name = bad_parameter_type.group(0)
1605             error(parameter.row, 'readability/pass_ptr', 5,
1606                   'The parameter type should use Pass%s instead of %s.' % (type_name, type_name))
1607
1608         # Do checks specific to function declarations and parameter names.
1609         if not function_state.is_declaration or not parameter.name:
1610             continue
1611
1612         # Check the parameter name against the function name for single parameter set functions.
1613         if len(parameter_list) == 1 and match('set[A-Z]', function_state.current_function):
1614             trimmed_function_name = function_state.current_function[len('set'):]
1615             if not _check_parameter_name_against_text(parameter, trimmed_function_name, error):
1616                 continue  # Since an error was noted for this name, move to the next parameter.
1617
1618         # Check the parameter name against the type.
1619         if not _check_parameter_name_against_text(parameter, parameter.type, error):
1620             continue  # Since an error was noted for this name, move to the next parameter.
1621
1622
1623 def check_pass_ptr_usage(clean_lines, line_number, function_state, error):
1624     """Check for proper usage of Pass*Ptr.
1625
1626     Currently this is limited to detecting declarations of Pass*Ptr
1627     variables inside of functions.
1628
1629     Args:
1630       clean_lines: A CleansedLines instance containing the file.
1631       line_number: The number of the line to check.
1632       function_state: Current function name and lines in body so far.
1633       error: The function to call with any errors found.
1634     """
1635     if not function_state.in_a_function:
1636         return
1637
1638     lines = clean_lines.lines
1639     line = lines[line_number]
1640     if line_number > function_state.body_start_position.row:
1641         matched_pass_ptr = match(r'^\s*Pass([A-Z][A-Za-z]*)Ptr<', line)
1642         if matched_pass_ptr:
1643             type_name = 'Pass%sPtr' % matched_pass_ptr.group(1)
1644             error(line_number, 'readability/pass_ptr', 5,
1645                   'Local variables should never be %s (see '
1646                   'http://webkit.org/coding/RefPtr.html).' % type_name)
1647
1648
1649 def check_spacing(file_extension, clean_lines, line_number, error):
1650     """Checks for the correctness of various spacing issues in the code.
1651
1652     Things we check for: spaces around operators, spaces after
1653     if/for/while/switch, no spaces around parens in function calls, two
1654     spaces between code and comment, don't start a block with a blank
1655     line, don't end a function with a blank line, don't have too many
1656     blank lines in a row.
1657
1658     Args:
1659       file_extension: The current file extension, without the leading dot.
1660       clean_lines: A CleansedLines instance containing the file.
1661       line_number: The number of the line to check.
1662       error: The function to call with any errors found.
1663     """
1664
1665     raw = clean_lines.raw_lines
1666     line = raw[line_number]
1667
1668     # Before nixing comments, check if the line is blank for no good
1669     # reason.  This includes the first line after a block is opened, and
1670     # blank lines at the end of a function (ie, right before a line like '}').
1671     if is_blank_line(line):
1672         elided = clean_lines.elided
1673         previous_line = elided[line_number - 1]
1674         previous_brace = previous_line.rfind('{')
1675         # FIXME: Don't complain if line before blank line, and line after,
1676         #        both start with alnums and are indented the same amount.
1677         #        This ignores whitespace at the start of a namespace block
1678         #        because those are not usually indented.
1679         if (previous_brace != -1 and previous_line[previous_brace:].find('}') == -1
1680             and previous_line[:previous_brace].find('namespace') == -1):
1681             # OK, we have a blank line at the start of a code block.  Before we
1682             # complain, we check if it is an exception to the rule: The previous
1683             # non-empty line has the parameters of a function header that are indented
1684             # 4 spaces (because they did not fit in a 80 column line when placed on
1685             # the same line as the function name).  We also check for the case where
1686             # the previous line is indented 6 spaces, which may happen when the
1687             # initializers of a constructor do not fit into a 80 column line.
1688             exception = False
1689             if match(r' {6}\w', previous_line):  # Initializer list?
1690                 # We are looking for the opening column of initializer list, which
1691                 # should be indented 4 spaces to cause 6 space indentation afterwards.
1692                 search_position = line_number - 2
1693                 while (search_position >= 0
1694                        and match(r' {6}\w', elided[search_position])):
1695                     search_position -= 1
1696                 exception = (search_position >= 0
1697                              and elided[search_position][:5] == '    :')
1698             else:
1699                 # Search for the function arguments or an initializer list.  We use a
1700                 # simple heuristic here: If the line is indented 4 spaces; and we have a
1701                 # closing paren, without the opening paren, followed by an opening brace
1702                 # or colon (for initializer lists) we assume that it is the last line of
1703                 # a function header.  If we have a colon indented 4 spaces, it is an
1704                 # initializer list.
1705                 exception = (match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)',
1706                                    previous_line)
1707                              or match(r' {4}:', previous_line))
1708
1709             if not exception:
1710                 error(line_number, 'whitespace/blank_line', 2,
1711                       'Blank line at the start of a code block.  Is this needed?')
1712         # This doesn't ignore whitespace at the end of a namespace block
1713         # because that is too hard without pairing open/close braces;
1714         # however, a special exception is made for namespace closing
1715         # brackets which have a comment containing "namespace".
1716         #
1717         # Also, ignore blank lines at the end of a block in a long if-else
1718         # chain, like this:
1719         #   if (condition1) {
1720         #     // Something followed by a blank line
1721         #
1722         #   } else if (condition2) {
1723         #     // Something else
1724         #   }
1725         if line_number + 1 < clean_lines.num_lines():
1726             next_line = raw[line_number + 1]
1727             if (next_line
1728                 and match(r'\s*}', next_line)
1729                 and next_line.find('namespace') == -1
1730                 and next_line.find('} else ') == -1):
1731                 error(line_number, 'whitespace/blank_line', 3,
1732                       'Blank line at the end of a code block.  Is this needed?')
1733
1734     # Next, we check for proper spacing with respect to comments.
1735     comment_position = line.find('//')
1736     if comment_position != -1:
1737         # Check if the // may be in quotes.  If so, ignore it
1738         # Comparisons made explicit for clarity -- pylint: disable-msg=C6403
1739         if (line.count('"', 0, comment_position) - line.count('\\"', 0, comment_position)) % 2 == 0:   # not in quotes
1740             # Allow one space before end of line comment.
1741             if (not match(r'^\s*$', line[:comment_position])
1742                 and (comment_position >= 1
1743                 and ((line[comment_position - 1] not in string.whitespace)
1744                      or (comment_position >= 2
1745                          and line[comment_position - 2] in string.whitespace)))):
1746                 error(line_number, 'whitespace/comments', 5,
1747                       'One space before end of line comments')
1748             # There should always be a space between the // and the comment
1749             commentend = comment_position + 2
1750             if commentend < len(line) and not line[commentend] == ' ':
1751                 # but some lines are exceptions -- e.g. if they're big
1752                 # comment delimiters like:
1753                 # //----------------------------------------------------------
1754                 # or they begin with multiple slashes followed by a space:
1755                 # //////// Header comment
1756                 matched = (search(r'[=/-]{4,}\s*$', line[commentend:])
1757                            or search(r'^/+ ', line[commentend:]))
1758                 if not matched:
1759                     error(line_number, 'whitespace/comments', 4,
1760                           'Should have a space between // and comment')
1761
1762             # There should only be one space after punctuation in a comment.
1763             if search(r'[.!?,;:]\s\s+\w', line[comment_position:]):
1764                 error(line_number, 'whitespace/comments', 5,
1765                       'Should have only a single space after a punctuation in a comment.')
1766
1767     line = clean_lines.elided[line_number]  # get rid of comments and strings
1768
1769     # Don't try to do spacing checks for operator methods
1770     line = sub(r'operator(==|!=|<|<<|<=|>=|>>|>|\+=|-=|\*=|/=|%=|&=|\|=|^=|<<=|>>=)\(', 'operator\(', line)
1771     # Don't try to do spacing checks for #include or #import statements at
1772     # minimum because it messes up checks for spacing around /
1773     if match(r'\s*#\s*(?:include|import)', line):
1774         return
1775     if search(r'[\w.]=[\w.]', line):
1776         error(line_number, 'whitespace/operators', 4,
1777               'Missing spaces around =')
1778
1779     # FIXME: It's not ok to have spaces around binary operators like .
1780
1781     # You should always have whitespace around binary operators.
1782     # Alas, we can't test < or > because they're legitimately used sans spaces
1783     # (a->b, vector<int> a).  The only time we can tell is a < with no >, and
1784     # only if it's not template params list spilling into the next line.
1785     matched = search(r'[^<>=!\s](==|!=|\+=|-=|\*=|/=|/|\|=|&=|<<=|>>=|<=|>=|\|\||\||&&|>>|<<)[^<>=!\s]', line)
1786     if not matched:
1787         # Note that while it seems that the '<[^<]*' term in the following
1788         # regexp could be simplified to '<.*', which would indeed match
1789         # the same class of strings, the [^<] means that searching for the
1790         # regexp takes linear rather than quadratic time.
1791         if not search(r'<[^<]*,\s*$', line):  # template params spill
1792             matched = search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line)
1793     if matched:
1794         error(line_number, 'whitespace/operators', 3,
1795               'Missing spaces around %s' % matched.group(1))
1796
1797     # There shouldn't be space around unary operators
1798     matched = search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
1799     if matched:
1800         error(line_number, 'whitespace/operators', 4,
1801               'Extra space for operator %s' % matched.group(1))
1802
1803     # A pet peeve of mine: no spaces after an if, while, switch, or for
1804     matched = search(r' (if\(|for\(|foreach\(|while\(|switch\()', line)
1805     if matched:
1806         error(line_number, 'whitespace/parens', 5,
1807               'Missing space before ( in %s' % matched.group(1))
1808
1809     # For if/for/foreach/while/switch, the left and right parens should be
1810     # consistent about how many spaces are inside the parens, and
1811     # there should either be zero or one spaces inside the parens.
1812     # We don't want: "if ( foo)" or "if ( foo   )".
1813     # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed.
1814     matched = search(r'\b(?P<statement>if|for|foreach|while|switch)\s*\((?P<remainder>.*)$', line)
1815     if matched:
1816         statement = matched.group('statement')
1817         condition, rest = up_to_unmatched_closing_paren(matched.group('remainder'))
1818         if condition is not None:
1819             condition_match = search(r'(?P<leading>[ ]*)(?P<separator>.).*[^ ]+(?P<trailing>[ ]*)', condition)
1820             if condition_match:
1821                 n_leading = len(condition_match.group('leading'))
1822                 n_trailing = len(condition_match.group('trailing'))
1823                 if n_leading != 0:
1824                     for_exception = statement == 'for' and condition.startswith(' ;')
1825                     if not for_exception:
1826                         error(line_number, 'whitespace/parens', 5,
1827                               'Extra space after ( in %s' % statement)
1828                 if n_trailing != 0:
1829                     for_exception = statement == 'for' and condition.endswith('; ')
1830                     if not for_exception:
1831                         error(line_number, 'whitespace/parens', 5,
1832                               'Extra space before ) in %s' % statement)
1833
1834             # Do not check for more than one command in macros
1835             in_preprocessor_directive = match(r'\s*#', line)
1836             if not in_preprocessor_directive and not match(r'((\s*{\s*}?)|(\s*;?))\s*\\?$', rest):
1837                 error(line_number, 'whitespace/parens', 4,
1838                       'More than one command on the same line in %s' % statement)
1839
1840     # You should always have a space after a comma (either as fn arg or operator)
1841     if search(r',[^\s]', line):
1842         error(line_number, 'whitespace/comma', 3,
1843               'Missing space after ,')
1844
1845     matched = search(r'^\s*(?P<token1>[a-zA-Z0-9_\*&]+)\s\s+(?P<token2>[a-zA-Z0-9_\*&]+)', line)
1846     if matched:
1847         error(line_number, 'whitespace/declaration', 3,
1848               'Extra space between %s and %s' % (matched.group('token1'), matched.group('token2')))
1849
1850     if file_extension == 'cpp':
1851         # C++ should have the & or * beside the type not the variable name.
1852         matched = match(r'\s*\w+(?<!\breturn|\bdelete)\s+(?P<pointer_operator>\*|\&)\w+', line)
1853         if matched:
1854             error(line_number, 'whitespace/declaration', 3,
1855                   'Declaration has space between type name and %s in %s' % (matched.group('pointer_operator'), matched.group(0).strip()))
1856
1857     elif file_extension == 'c':
1858         # C Pointer declaration should have the * beside the variable not the type name.
1859         matched = search(r'^\s*\w+\*\s+\w+', line)
1860         if matched:
1861             error(line_number, 'whitespace/declaration', 3,
1862                   'Declaration has space between * and variable name in %s' % matched.group(0).strip())
1863
1864     # Next we will look for issues with function calls.
1865     check_spacing_for_function_call(line, line_number, error)
1866
1867     # Except after an opening paren, you should have spaces before your braces.
1868     # And since you should never have braces at the beginning of a line, this is
1869     # an easy test.
1870     if search(r'[^ ({]{', line):
1871         error(line_number, 'whitespace/braces', 5,
1872               'Missing space before {')
1873
1874     # Make sure '} else {' has spaces.
1875     if search(r'}else', line):
1876         error(line_number, 'whitespace/braces', 5,
1877               'Missing space before else')
1878
1879     # You shouldn't have spaces before your brackets, except maybe after
1880     # 'delete []' or 'new char * []'.
1881     if search(r'\w\s+\[', line) and not search(r'delete\s+\[', line):
1882         error(line_number, 'whitespace/braces', 5,
1883               'Extra space before [')
1884
1885     # There should always be a single space in between braces on the same line.
1886     if search(r'\{\}', line):
1887         error(line_number, 'whitespace/braces', 5, 'Missing space inside { }.')
1888     if search(r'\{\s\s+\}', line):
1889         error(line_number, 'whitespace/braces', 5, 'Too many spaces inside { }.')
1890
1891     # You shouldn't have a space before a semicolon at the end of the line.
1892     # There's a special case for "for" since the style guide allows space before
1893     # the semicolon there.
1894     if search(r':\s*;\s*$', line):
1895         error(line_number, 'whitespace/semicolon', 5,
1896               'Semicolon defining empty statement. Use { } instead.')
1897     elif search(r'^\s*;\s*$', line):
1898         error(line_number, 'whitespace/semicolon', 5,
1899               'Line contains only semicolon. If this should be an empty statement, '
1900               'use { } instead.')
1901     elif (search(r'\s+;\s*$', line) and not search(r'\bfor\b', line)):
1902         error(line_number, 'whitespace/semicolon', 5,
1903               'Extra space before last semicolon. If this should be an empty '
1904               'statement, use { } instead.')
1905     elif (search(r'\b(for|while)\s*\(.*\)\s*;\s*$', line)
1906           and line.count('(') == line.count(')')
1907           # Allow do {} while();
1908           and not search(r'}\s*while', line)):
1909         error(line_number, 'whitespace/semicolon', 5,
1910               'Semicolon defining empty statement for this loop. Use { } instead.')
1911
1912
1913 def get_previous_non_blank_line(clean_lines, line_number):
1914     """Return the most recent non-blank line and its line number.
1915
1916     Args:
1917       clean_lines: A CleansedLines instance containing the file contents.
1918       line_number: The number of the line to check.
1919
1920     Returns:
1921       A tuple with two elements.  The first element is the contents of the last
1922       non-blank line before the current line, or the empty string if this is the
1923       first non-blank line.  The second is the line number of that line, or -1
1924       if this is the first non-blank line.
1925     """
1926
1927     previous_line_number = line_number - 1
1928     while previous_line_number >= 0:
1929         previous_line = clean_lines.elided[previous_line_number]
1930         if not is_blank_line(previous_line):     # if not a blank line...
1931             return (previous_line, previous_line_number)
1932         previous_line_number -= 1
1933     return ('', -1)
1934
1935
1936 def check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error):
1937     """Looks for indentation errors inside of namespaces.
1938
1939     Args:
1940       clean_lines: A CleansedLines instance containing the file.
1941       line_number: The number of the line to check.
1942       file_extension: The extension (dot not included) of the file.
1943       file_state: A _FileState instance which maintains information about
1944                   the state of things in the file.
1945       error: The function to call with any errors found.
1946     """
1947
1948     line = clean_lines.elided[line_number] # Get rid of comments and strings.
1949
1950     namespace_match = match(r'(?P<namespace_indentation>\s*)namespace\s+\S+\s*{\s*$', line)
1951     if not namespace_match:
1952         return
1953
1954     current_indentation_level = len(namespace_match.group('namespace_indentation'))
1955     if current_indentation_level > 0:
1956         # Don't warn about an indented namespace if we already warned about indented code.
1957         if not file_state.did_inside_namespace_indent_warning():
1958             error(line_number, 'whitespace/indent', 4,
1959                   'namespace should never be indented.')
1960         return
1961     looking_for_semicolon = False;
1962     line_offset = 0
1963     in_preprocessor_directive = False;
1964     for current_line in clean_lines.elided[line_number + 1:]:
1965         line_offset += 1
1966         if not current_line.strip():
1967             continue
1968         if not current_indentation_level:
1969             if not (in_preprocessor_directive or looking_for_semicolon):
1970                 if not match(r'\S', current_line) and not file_state.did_inside_namespace_indent_warning():
1971                     file_state.set_did_inside_namespace_indent_warning()
1972                     error(line_number + line_offset, 'whitespace/indent', 4,
1973                           'Code inside a namespace should not be indented.')
1974             if in_preprocessor_directive or (current_line.strip()[0] == '#'): # This takes care of preprocessor directive syntax.
1975                 in_preprocessor_directive = current_line[-1] == '\\'
1976             else:
1977                 looking_for_semicolon = ((current_line.find(';') == -1) and (current_line.strip()[-1] != '}')) or (current_line[-1] == '\\')
1978         else:
1979             looking_for_semicolon = False; # If we have a brace we may not need a semicolon.
1980         current_indentation_level += current_line.count('{') - current_line.count('}')
1981         if current_indentation_level < 0:
1982             break;
1983
1984
1985 def check_using_std(clean_lines, line_number, file_state, error):
1986     """Looks for 'using std::foo;' statements which should be replaced with 'using namespace std;'.
1987
1988     Args:
1989       clean_lines: A CleansedLines instance containing the file.
1990       line_number: The number of the line to check.
1991       file_state: A _FileState instance which maintains information about
1992                   the state of things in the file.
1993       error: The function to call with any errors found.
1994     """
1995
1996     # This check doesn't apply to C or Objective-C implementation files.
1997     if file_state.is_c_or_objective_c():
1998         return
1999
2000     line = clean_lines.elided[line_number] # Get rid of comments and strings.
2001
2002     using_std_match = match(r'\s*using\s+std::(?P<method_name>\S+)\s*;\s*$', line)
2003     if not using_std_match:
2004         return
2005
2006     method_name = using_std_match.group('method_name')
2007     error(line_number, 'build/using_std', 4,
2008           "Use 'using namespace std;' instead of 'using std::%s;'." % method_name)
2009
2010
2011 def check_max_min_macros(clean_lines, line_number, file_state, error):
2012     """Looks use of MAX() and MIN() macros that should be replaced with std::max() and std::min().
2013
2014     Args:
2015       clean_lines: A CleansedLines instance containing the file.
2016       line_number: The number of the line to check.
2017       file_state: A _FileState instance which maintains information about
2018                   the state of things in the file.
2019       error: The function to call with any errors found.
2020     """
2021
2022     # This check doesn't apply to C or Objective-C implementation files.
2023     if file_state.is_c_or_objective_c():
2024         return
2025
2026     line = clean_lines.elided[line_number] # Get rid of comments and strings.
2027
2028     max_min_macros_search = search(r'\b(?P<max_min_macro>(MAX|MIN))\s*\(', line)
2029     if not max_min_macros_search:
2030         return
2031
2032     max_min_macro = max_min_macros_search.group('max_min_macro')
2033     max_min_macro_lower = max_min_macro.lower()
2034     error(line_number, 'runtime/max_min_macros', 4,
2035           'Use std::%s() or std::%s<type>() instead of the %s() macro.'
2036           % (max_min_macro_lower, max_min_macro_lower, max_min_macro))
2037
2038
2039 def check_switch_indentation(clean_lines, line_number, error):
2040     """Looks for indentation errors inside of switch statements.
2041
2042     Args:
2043       clean_lines: A CleansedLines instance containing the file.
2044       line_number: The number of the line to check.
2045       error: The function to call with any errors found.
2046     """
2047
2048     line = clean_lines.elided[line_number] # Get rid of comments and strings.
2049
2050     switch_match = match(r'(?P<switch_indentation>\s*)switch\s*\(.+\)\s*{\s*$', line)
2051     if not switch_match:
2052         return
2053
2054     switch_indentation = switch_match.group('switch_indentation')
2055     inner_indentation = switch_indentation + ' ' * 4
2056     line_offset = 0
2057     encountered_nested_switch = False
2058
2059     for current_line in clean_lines.elided[line_number + 1:]:
2060         line_offset += 1
2061
2062         # Skip not only empty lines but also those with preprocessor directives.
2063         if current_line.strip() == '' or current_line.startswith('#'):
2064             continue
2065
2066         if match(r'\s*switch\s*\(.+\)\s*{\s*$', current_line):
2067             # Complexity alarm - another switch statement nested inside the one
2068             # that we're currently testing. We'll need to track the extent of
2069             # that inner switch if the upcoming label tests are still supposed
2070             # to work correctly. Let's not do that; instead, we'll finish
2071             # checking this line, and then leave it like that. Assuming the
2072             # indentation is done consistently (even if incorrectly), this will
2073             # still catch all indentation issues in practice.
2074             encountered_nested_switch = True
2075
2076         current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line);
2077         current_indentation = current_indentation_match.group('indentation')
2078         remaining_line = current_indentation_match.group('remaining_line')
2079
2080         # End the check at the end of the switch statement.
2081         if remaining_line.startswith('}') and current_indentation == switch_indentation:
2082             break
2083         # Case and default branches should not be indented. The regexp also
2084         # catches single-line cases like "default: break;" but does not trigger
2085         # on stuff like "Document::Foo();".
2086         elif match(r'(default|case\s+.*)\s*:([^:].*)?$', remaining_line):
2087             if current_indentation != switch_indentation:
2088                 error(line_number + line_offset, 'whitespace/indent', 4,
2089                       'A case label should not be indented, but line up with its switch statement.')
2090                 # Don't throw an error for multiple badly indented labels,
2091                 # one should be enough to figure out the problem.
2092                 break
2093         # We ignore goto labels at the very beginning of a line.
2094         elif match(r'\w+\s*:\s*$', remaining_line):
2095             continue
2096         # It's not a goto label, so check if it's indented at least as far as
2097         # the switch statement plus one more level of indentation.
2098         elif not current_indentation.startswith(inner_indentation):
2099             error(line_number + line_offset, 'whitespace/indent', 4,
2100                   'Non-label code inside switch statements should be indented.')
2101             # Don't throw an error for multiple badly indented statements,
2102             # one should be enough to figure out the problem.
2103             break
2104
2105         if encountered_nested_switch:
2106             break
2107
2108
2109 def check_braces(clean_lines, line_number, error):
2110     """Looks for misplaced braces (e.g. at the end of line).
2111
2112     Args:
2113       clean_lines: A CleansedLines instance containing the file.
2114       line_number: The number of the line to check.
2115       error: The function to call with any errors found.
2116     """
2117
2118     line = clean_lines.elided[line_number] # Get rid of comments and strings.
2119
2120     if match(r'\s*{\s*$', line):
2121         # We allow an open brace to start a line in the case where someone
2122         # is using braces for function definition or in a block to
2123         # explicitly create a new scope, which is commonly used to control
2124         # the lifetime of stack-allocated variables.  We don't detect this
2125         # perfectly: we just don't complain if the last non-whitespace
2126         # character on the previous non-blank line is ';', ':', '{', '}',
2127         # ')', or ') const' and doesn't begin with 'if|for|while|switch|else'.
2128         # We also allow '#' for #endif and '=' for array initialization.
2129         previous_line = get_previous_non_blank_line(clean_lines, line_number)[0]
2130         if ((not search(r'[;:}{)=]\s*$|\)\s*const\s*$', previous_line)
2131              or search(r'\b(if|for|foreach|while|switch|else)\b', previous_line))
2132             and previous_line.find('#') < 0):
2133             error(line_number, 'whitespace/braces', 4,
2134                   'This { should be at the end of the previous line')
2135     elif (search(r'\)\s*(const\s*)?{\s*$', line)
2136           and line.count('(') == line.count(')')
2137           and not search(r'\b(if|for|foreach|while|switch)\b', line)
2138           and not match(r'\s+[A-Z_][A-Z_0-9]+\b', line)):
2139         error(line_number, 'whitespace/braces', 4,
2140               'Place brace on its own line for function definitions.')
2141
2142     if (match(r'\s*}\s*(else\s*({\s*)?)?$', line) and line_number > 1):
2143         # We check if a closed brace has started a line to see if a
2144         # one line control statement was previous.
2145         previous_line = clean_lines.elided[line_number - 2]
2146         last_open_brace = previous_line.rfind('{')
2147         if (last_open_brace != -1 and previous_line.find('}', last_open_brace) == -1
2148             and search(r'\b(if|for|foreach|while|else)\b', previous_line)):
2149             error(line_number, 'whitespace/braces', 4,
2150                   'One line control clauses should not use braces.')
2151
2152     # An else clause should be on the same line as the preceding closing brace.
2153     if match(r'\s*else\s*', line):
2154         previous_line = get_previous_non_blank_line(clean_lines, line_number)[0]
2155         if match(r'\s*}\s*$', previous_line):
2156             error(line_number, 'whitespace/newline', 4,
2157                   'An else should appear on the same line as the preceding }')
2158
2159     # Likewise, an else should never have the else clause on the same line
2160     if search(r'\belse [^\s{]', line) and not search(r'\belse if\b', line):
2161         error(line_number, 'whitespace/newline', 4,
2162               'Else clause should never be on same line as else (use 2 lines)')
2163
2164     # In the same way, a do/while should never be on one line
2165     if match(r'\s*do [^\s{]', line):
2166         error(line_number, 'whitespace/newline', 4,
2167               'do/while clauses should not be on a single line')
2168
2169     # Braces shouldn't be followed by a ; unless they're defining a struct
2170     # or initializing an array.
2171     # We can't tell in general, but we can for some common cases.
2172     previous_line_number = line_number
2173     while True:
2174         (previous_line, previous_line_number) = get_previous_non_blank_line(clean_lines, previous_line_number)
2175         if match(r'\s+{.*}\s*;', line) and not previous_line.count(';'):
2176             line = previous_line + line
2177         else:
2178             break
2179     if (search(r'{.*}\s*;', line)
2180         and line.count('{') == line.count('}')
2181         and not search(r'struct|class|enum|\s*=\s*{', line)):
2182         error(line_number, 'readability/braces', 4,
2183               "You don't need a ; after a }")
2184
2185
2186 def check_exit_statement_simplifications(clean_lines, line_number, error):
2187     """Looks for else or else-if statements that should be written as an
2188     if statement when the prior if concludes with a return, break, continue or
2189     goto statement.
2190
2191     Args:
2192       clean_lines: A CleansedLines instance containing the file.
2193       line_number: The number of the line to check.
2194       error: The function to call with any errors found.
2195     """
2196
2197     line = clean_lines.elided[line_number] # Get rid of comments and strings.
2198
2199     else_match = match(r'(?P<else_indentation>\s*)(\}\s*)?else(\s+if\s*\(|(?P<else>\s*(\{\s*)?\Z))', line)
2200     if not else_match:
2201         return
2202
2203     else_indentation = else_match.group('else_indentation')
2204     inner_indentation = else_indentation + ' ' * 4
2205
2206     previous_lines = clean_lines.elided[:line_number]
2207     previous_lines.reverse()
2208     line_offset = 0
2209     encountered_exit_statement = False
2210
2211     for current_line in previous_lines:
2212         line_offset -= 1
2213
2214         # Skip not only empty lines but also those with preprocessor directives
2215         # and goto labels.
2216         if current_line.strip() == '' or current_line.startswith('#') or match(r'\w+\s*:\s*$', current_line):
2217             continue
2218
2219         # Skip lines with closing braces on the original indentation level.
2220         # Even though the styleguide says they should be on the same line as
2221         # the "else if" statement, we also want to check for instances where
2222         # the current code does not comply with the coding style. Thus, ignore
2223         # these lines and proceed to the line before that.
2224         if current_line == else_indentation + '}':
2225             continue
2226
2227         current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line);
2228         current_indentation = current_indentation_match.group('indentation')
2229         remaining_line = current_indentation_match.group('remaining_line')
2230
2231         # As we're going up the lines, the first real statement to encounter
2232         # has to be an exit statement (return, break, continue or goto) -
2233         # otherwise, this check doesn't apply.
2234         if not encountered_exit_statement:
2235             # We only want to find exit statements if they are on exactly
2236             # the same level of indentation as expected from the code inside
2237             # the block. If the indentation doesn't strictly match then we
2238             # might have a nested if or something, which must be ignored.
2239             if current_indentation != inner_indentation:
2240                 break
2241             if match(r'(return(\W+.*)|(break|continue)\s*;|goto\s*\w+;)$', remaining_line):
2242                 encountered_exit_statement = True
2243                 continue
2244             break
2245
2246         # When code execution reaches this point, we've found an exit statement
2247         # as last statement of the previous block. Now we only need to make
2248         # sure that the block belongs to an "if", then we can throw an error.
2249
2250         # Skip lines with opening braces on the original indentation level,
2251         # similar to the closing braces check above. ("if (condition)\n{")
2252         if current_line == else_indentation + '{':
2253             continue
2254
2255         # Skip everything that's further indented than our "else" or "else if".
2256         if current_indentation.startswith(else_indentation) and current_indentation != else_indentation:
2257             continue
2258
2259         # So we've got a line with same (or less) indentation. Is it an "if"?
2260         # If yes: throw an error. If no: don't throw an error.
2261         # Whatever the outcome, this is the end of our loop.
2262         if match(r'if\s*\(', remaining_line):
2263             if else_match.start('else') != -1:
2264                 error(line_number + line_offset, 'readability/control_flow', 4,
2265                       'An else statement can be removed when the prior "if" '
2266                       'concludes with a return, break, continue or goto statement.')
2267             else:
2268                 error(line_number + line_offset, 'readability/control_flow', 4,
2269                       'An else if statement should be written as an if statement '
2270                       'when the prior "if" concludes with a return, break, '
2271                       'continue or goto statement.')
2272         break
2273
2274
2275 def replaceable_check(operator, macro, line):
2276     """Determine whether a basic CHECK can be replaced with a more specific one.
2277
2278     For example suggest using CHECK_EQ instead of CHECK(a == b) and
2279     similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE.
2280
2281     Args:
2282       operator: The C++ operator used in the CHECK.
2283       macro: The CHECK or EXPECT macro being called.
2284       line: The current source line.
2285
2286     Returns:
2287       True if the CHECK can be replaced with a more specific one.
2288     """
2289
2290     # This matches decimal and hex integers, strings, and chars (in that order).
2291     match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')'
2292
2293     # Expression to match two sides of the operator with something that
2294     # looks like a literal, since CHECK(x == iterator) won't compile.
2295     # This means we can't catch all the cases where a more specific
2296     # CHECK is possible, but it's less annoying than dealing with
2297     # extraneous warnings.
2298     match_this = (r'\s*' + macro + r'\((\s*' +
2299                   match_constant + r'\s*' + operator + r'[^<>].*|'
2300                   r'.*[^<>]' + operator + r'\s*' + match_constant +
2301                   r'\s*\))')
2302
2303     # Don't complain about CHECK(x == NULL) or similar because
2304     # CHECK_EQ(x, NULL) won't compile (requires a cast).
2305     # Also, don't complain about more complex boolean expressions
2306     # involving && or || such as CHECK(a == b || c == d).
2307     return match(match_this, line) and not search(r'NULL|&&|\|\|', line)
2308
2309
2310 def check_check(clean_lines, line_number, error):
2311     """Checks the use of CHECK and EXPECT macros.
2312
2313     Args:
2314       clean_lines: A CleansedLines instance containing the file.
2315       line_number: The number of the line to check.
2316       error: The function to call with any errors found.
2317     """
2318
2319     # Decide the set of replacement macros that should be suggested
2320     raw_lines = clean_lines.raw_lines
2321     current_macro = ''
2322     for macro in _CHECK_MACROS:
2323         if raw_lines[line_number].find(macro) >= 0:
2324             current_macro = macro
2325             break
2326     if not current_macro:
2327         # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT'
2328         return
2329
2330     line = clean_lines.elided[line_number]        # get rid of comments and strings
2331
2332     # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc.
2333     for operator in ['==', '!=', '>=', '>', '<=', '<']:
2334         if replaceable_check(operator, current_macro, line):
2335             error(line_number, 'readability/check', 2,
2336                   'Consider using %s instead of %s(a %s b)' % (
2337                       _CHECK_REPLACEMENT[current_macro][operator],
2338                       current_macro, operator))
2339             break
2340
2341
2342 def check_for_comparisons_to_zero(clean_lines, line_number, error):
2343     # Get the line without comments and strings.
2344     line = clean_lines.elided[line_number]
2345
2346     # Include NULL here so that users don't have to convert NULL to 0 first and then get this error.
2347     if search(r'[=!]=\s*(NULL|0|true|false)\W', line) or search(r'\W(NULL|0|true|false)\s*[=!]=', line):
2348         if not search('LIKELY', line) and not search('UNLIKELY', line):
2349             error(line_number, 'readability/comparison_to_zero', 5,
2350                   'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.')
2351
2352
2353 def check_for_null(clean_lines, line_number, file_state, error):
2354     # This check doesn't apply to C or Objective-C implementation files.
2355     if file_state.is_c_or_objective_c():
2356         return
2357
2358     line = clean_lines.elided[line_number]
2359
2360     # Don't warn about NULL usage in g_*(). See Bug 32858 and 39372.
2361     if search(r'\bg(_[a-z]+)+\b', line):
2362         return
2363
2364     # Don't warn about NULL usage in gst_*_many(). See Bug 39740
2365     if search(r'\bgst_\w+_many\b', line):
2366         return
2367
2368     # Don't warn about NULL usage in g_str{join,concat}(). See Bug 34834
2369     if search(r'\bg_str(join|concat)\b', line):
2370         return
2371
2372     # Don't warn about NULL usage in gdk_pixbuf_save_to_*{join,concat}(). See Bug 43090.
2373     if search(r'\bgdk_pixbuf_save_to\w+\b', line):
2374         return
2375
2376     # Don't warn about NULL usage in gtk_widget_style_get(). See Bug 51758.
2377     if search(r'\bgtk_widget_style_get\(\w+\b', line):
2378         return
2379
2380     if search(r'\bNULL\b', line):
2381         error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.')
2382         return
2383
2384     line = clean_lines.raw_lines[line_number]
2385     # See if NULL occurs in any comments in the line. If the search for NULL using the raw line
2386     # matches, then do the check with strings collapsed to avoid giving errors for
2387     # NULLs occurring in strings.
2388     if search(r'\bNULL\b', line) and search(r'\bNULL\b', CleansedLines.collapse_strings(line)):
2389         error(line_number, 'readability/null', 4, 'Use 0 or null instead of NULL (even in *comments*).')
2390
2391 def get_line_width(line):
2392     """Determines the width of the line in column positions.
2393
2394     Args:
2395       line: A string, which may be a Unicode string.
2396
2397     Returns:
2398       The width of the line in column positions, accounting for Unicode
2399       combining characters and wide characters.
2400     """
2401     if isinstance(line, unicode):
2402         width = 0
2403         for c in unicodedata.normalize('NFC', line):
2404             if unicodedata.east_asian_width(c) in ('W', 'F'):
2405                 width += 2
2406             elif not unicodedata.combining(c):
2407                 width += 1
2408         return width
2409     return len(line)
2410
2411
2412 def check_style(clean_lines, line_number, file_extension, class_state, file_state, error):
2413     """Checks rules from the 'C++ style rules' section of cppguide.html.
2414
2415     Most of these rules are hard to test (naming, comment style), but we
2416     do what we can.  In particular we check for 4-space indents, line lengths,
2417     tab usage, spaces inside code, etc.
2418
2419     Args:
2420       clean_lines: A CleansedLines instance containing the file.
2421       line_number: The number of the line to check.
2422       file_extension: The extension (without the dot) of the filename.
2423       class_state: A _ClassState instance which maintains information about
2424                    the current stack of nested class declarations being parsed.
2425       file_state: A _FileState instance which maintains information about
2426                   the state of things in the file.
2427       error: The function to call with any errors found.
2428     """
2429
2430     raw_lines = clean_lines.raw_lines
2431     line = raw_lines[line_number]
2432
2433     if line.find('\t') != -1:
2434         error(line_number, 'whitespace/tab', 1,
2435               'Tab found; better to use spaces')
2436
2437     # One or three blank spaces at the beginning of the line is weird; it's
2438     # hard to reconcile that with 4-space indents.
2439     # NOTE: here are the conditions rob pike used for his tests.  Mine aren't
2440     # as sophisticated, but it may be worth becoming so:  RLENGTH==initial_spaces
2441     # if(RLENGTH > 20) complain = 0;
2442     # if(match($0, " +(error|private|public|protected):")) complain = 0;
2443     # if(match(prev, "&& *$")) complain = 0;
2444     # if(match(prev, "\\|\\| *$")) complain = 0;
2445     # if(match(prev, "[\",=><] *$")) complain = 0;
2446     # if(match($0, " <<")) complain = 0;
2447     # if(match(prev, " +for \\(")) complain = 0;
2448     # if(prevodd && match(prevprev, " +for \\(")) complain = 0;
2449     initial_spaces = 0
2450     cleansed_line = clean_lines.elided[line_number]
2451     while initial_spaces < len(line) and line[initial_spaces] == ' ':
2452         initial_spaces += 1
2453     if line and line[-1].isspace():
2454         error(line_number, 'whitespace/end_of_line', 4,
2455               'Line ends in whitespace.  Consider deleting these extra spaces.')
2456     # There are certain situations we allow one space, notably for labels
2457     elif ((initial_spaces >= 1 and initial_spaces <= 3)
2458           and not match(r'\s*\w+\s*:\s*$', cleansed_line)):
2459         error(line_number, 'whitespace/indent', 3,
2460               'Weird number of spaces at line-start.  '
2461               'Are you using a 4-space indent?')
2462     # Labels should always be indented at least one space.
2463     elif not initial_spaces and line[:2] != '//':
2464         label_match = match(r'(?P<label>[^:]+):\s*$', line)
2465
2466         if label_match:
2467             label = label_match.group('label')
2468             # Only throw errors for stuff that is definitely not a goto label,
2469             # because goto labels can in fact occur at the start of the line.
2470             if label in ['public', 'private', 'protected'] or label.find(' ') != -1:
2471                 error(line_number, 'whitespace/labels', 4,
2472                       'Labels should always be indented at least one space.  '
2473                       'If this is a member-initializer list in a constructor, '
2474                       'the colon should be on the line after the definition header.')
2475
2476     if (cleansed_line.count(';') > 1
2477         # for loops are allowed two ;'s (and may run over two lines).
2478         and cleansed_line.find('for') == -1
2479         and (get_previous_non_blank_line(clean_lines, line_number)[0].find('for') == -1
2480              or get_previous_non_blank_line(clean_lines, line_number)[0].find(';') != -1)
2481         # It's ok to have many commands in a switch case that fits in 1 line
2482         and not ((cleansed_line.find('case ') != -1
2483                   or cleansed_line.find('default:') != -1)
2484                  and cleansed_line.find('break;') != -1)
2485         # Also it's ok to have many commands in trivial single-line accessors in class definitions.
2486         and not (match(r'.*\(.*\).*{.*.}', line)
2487                  and class_state.classinfo_stack
2488                  and line.count('{') == line.count('}'))
2489         and not cleansed_line.startswith('#define ')):
2490         error(line_number, 'whitespace/newline', 4,
2491               'More than one command on the same line')
2492
2493     if cleansed_line.strip().endswith('||') or cleansed_line.strip().endswith('&&'):
2494         error(line_number, 'whitespace/operators', 4,
2495               'Boolean expressions that span multiple lines should have their '
2496               'operators on the left side of the line instead of the right side.')
2497
2498     # Some more style checks
2499     check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error)
2500     check_using_std(clean_lines, line_number, file_state, error)
2501     check_max_min_macros(clean_lines, line_number, file_state, error)
2502     check_switch_indentation(clean_lines, line_number, error)
2503     check_braces(clean_lines, line_number, error)
2504     check_exit_statement_simplifications(clean_lines, line_number, error)
2505     check_spacing(file_extension, clean_lines, line_number, error)
2506     check_check(clean_lines, line_number, error)
2507     check_for_comparisons_to_zero(clean_lines, line_number, error)
2508     check_for_null(clean_lines, line_number, file_state, error)
2509
2510
2511 _RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"')
2512 _RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$')
2513 # Matches the first component of a filename delimited by -s and _s. That is:
2514 #  _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo'
2515 #  _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo'
2516 #  _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo'
2517 #  _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo'
2518 _RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+')
2519
2520
2521 def _drop_common_suffixes(filename):
2522     """Drops common suffixes like _test.cpp or -inl.h from filename.
2523
2524     For example:
2525       >>> _drop_common_suffixes('foo/foo-inl.h')
2526       'foo/foo'
2527       >>> _drop_common_suffixes('foo/bar/foo.cpp')
2528       'foo/bar/foo'
2529       >>> _drop_common_suffixes('foo/foo_internal.h')
2530       'foo/foo'
2531       >>> _drop_common_suffixes('foo/foo_unusualinternal.h')
2532       'foo/foo_unusualinternal'
2533
2534     Args:
2535       filename: The input filename.
2536
2537     Returns:
2538       The filename with the common suffix removed.
2539     """
2540     for suffix in ('test.cpp', 'regtest.cpp', 'unittest.cpp',
2541                    'inl.h', 'impl.h', 'internal.h'):
2542         if (filename.endswith(suffix) and len(filename) > len(suffix)
2543             and filename[-len(suffix) - 1] in ('-', '_')):
2544             return filename[:-len(suffix) - 1]
2545     return os.path.splitext(filename)[0]
2546
2547
2548 def _classify_include(filename, include, is_system, include_state):
2549     """Figures out what kind of header 'include' is.
2550
2551     Args:
2552       filename: The current file cpp_style is running over.
2553       include: The path to a #included file.
2554       is_system: True if the #include used <> rather than "".
2555       include_state: An _IncludeState instance in which the headers are inserted.
2556
2557     Returns:
2558       One of the _XXX_HEADER constants.
2559
2560     For example:
2561       >>> _classify_include('foo.cpp', 'config.h', False)
2562       _CONFIG_HEADER
2563       >>> _classify_include('foo.cpp', 'foo.h', False)
2564       _PRIMARY_HEADER
2565       >>> _classify_include('foo.cpp', 'bar.h', False)
2566       _OTHER_HEADER
2567     """
2568
2569     # If it is a system header we know it is classified as _OTHER_HEADER.
2570     if is_system:
2571         return _OTHER_HEADER
2572
2573     # If the include is named config.h then this is WebCore/config.h.
2574     if include == "config.h":
2575         return _CONFIG_HEADER
2576
2577     # There cannot be primary includes in header files themselves. Only an
2578     # include exactly matches the header filename will be is flagged as
2579     # primary, so that it triggers the "don't include yourself" check.
2580     if filename.endswith('.h') and filename != include:
2581         return _OTHER_HEADER;
2582
2583     # Qt's moc files do not follow the naming and ordering rules, so they should be skipped
2584     if include.startswith('moc_') and include.endswith('.cpp'):
2585         return _MOC_HEADER
2586
2587     if include.endswith('.moc'):
2588         return _MOC_HEADER
2589
2590     # If the target file basename starts with the include we're checking
2591     # then we consider it the primary header.
2592     target_base = FileInfo(filename).base_name()
2593     include_base = FileInfo(include).base_name()
2594
2595     # If we haven't encountered a primary header, then be lenient in checking.
2596     if not include_state.visited_primary_section() and target_base.find(include_base) != -1:
2597         return _PRIMARY_HEADER
2598     # If we already encountered a primary header, perform a strict comparison.
2599     # In case the two filename bases are the same then the above lenient check
2600     # probably was a false positive.
2601     elif include_state.visited_primary_section() and target_base == include_base:
2602         if include == "ResourceHandleWin.h":
2603             # FIXME: Thus far, we've only seen one example of these, but if we
2604             # start to see more, please consider generalizing this check
2605             # somehow.
2606             return _OTHER_HEADER
2607         return _PRIMARY_HEADER
2608
2609     return _OTHER_HEADER
2610
2611
2612 def _does_primary_header_exist(filename):
2613     """Return a primary header file name for a file, or empty string
2614     if the file is not source file or primary header does not exist.
2615     """
2616     fileinfo = FileInfo(filename)
2617     if not fileinfo.is_source():
2618         return False
2619     primary_header = fileinfo.no_extension() + ".h"
2620     return os.path.isfile(primary_header)
2621
2622
2623 def check_include_line(filename, file_extension, clean_lines, line_number, include_state, error):
2624     """Check rules that are applicable to #include lines.
2625
2626     Strings on #include lines are NOT removed from elided line, to make
2627     certain tasks easier. However, to prevent false positives, checks
2628     applicable to #include lines in CheckLanguage must be put here.
2629
2630     Args:
2631       filename: The name of the current file.
2632       file_extension: The current file extension, without the leading dot.
2633       clean_lines: A CleansedLines instance containing the file.
2634       line_number: The number of the line to check.
2635       include_state: An _IncludeState instance in which the headers are inserted.
2636       error: The function to call with any errors found.
2637     """
2638     # FIXME: For readability or as a possible optimization, consider
2639     #        exiting early here by checking whether the "build/include"
2640     #        category should be checked for the given filename.  This
2641     #        may involve having the error handler classes expose a
2642     #        should_check() method, in addition to the usual __call__
2643     #        method.
2644     line = clean_lines.lines[line_number]
2645
2646     matched = _RE_PATTERN_INCLUDE.search(line)
2647     if not matched:
2648         return
2649
2650     include = matched.group(2)
2651     is_system = (matched.group(1) == '<')
2652
2653     # Look for any of the stream classes that are part of standard C++.
2654     if match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include):
2655         error(line_number, 'readability/streams', 3,
2656               'Streams are highly discouraged.')
2657
2658     # Look for specific includes to fix.
2659     if include.startswith('wtf/') and not is_system:
2660         error(line_number, 'build/include', 4,
2661               'wtf includes should be <wtf/file.h> instead of "wtf/file.h".')
2662
2663     duplicate_header = include in include_state
2664     if duplicate_header:
2665         error(line_number, 'build/include', 4,
2666               '"%s" already included at %s:%s' %
2667               (include, filename, include_state[include]))
2668     else:
2669         include_state[include] = line_number
2670
2671     header_type = _classify_include(filename, include, is_system, include_state)
2672     primary_header_exists = _does_primary_header_exist(filename)
2673     include_state.header_types[line_number] = header_type
2674
2675     # Only proceed if this isn't a duplicate header.
2676     if duplicate_header:
2677         return
2678
2679     # We want to ensure that headers appear in the right order:
2680     # 1) for implementation files: config.h, primary header, blank line, alphabetically sorted
2681     # 2) for header files: alphabetically sorted
2682     # The include_state object keeps track of the last type seen
2683     # and complains if the header types are out of order or missing.
2684     error_message = include_state.check_next_include_order(header_type,
2685                                                            file_extension == "h",
2686                                                            primary_header_exists)
2687
2688     # Check to make sure we have a blank line after primary header.
2689     if not error_message and header_type == _PRIMARY_HEADER:
2690          next_line = clean_lines.raw_lines[line_number + 1]
2691          if not is_blank_line(next_line):
2692             error(line_number, 'build/include_order', 4,
2693                   'You should add a blank line after implementation file\'s own header.')
2694
2695     # Check to make sure all headers besides config.h and the primary header are
2696     # alphabetically sorted. Skip Qt's moc files.
2697     if not error_message and header_type == _OTHER_HEADER:
2698          previous_line_number = line_number - 1;
2699          previous_line = clean_lines.lines[previous_line_number]
2700          previous_match = _RE_PATTERN_INCLUDE.search(previous_line)
2701          while (not previous_match and previous_line_number > 0
2702                 and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', previous_line)):
2703             previous_line_number -= 1;
2704             previous_line = clean_lines.lines[previous_line_number]
2705             previous_match = _RE_PATTERN_INCLUDE.search(previous_line)
2706          if previous_match:
2707             previous_header_type = include_state.header_types[previous_line_number]
2708             if previous_header_type == _OTHER_HEADER and previous_line.strip() > line.strip():
2709                 error(line_number, 'build/include_order', 4,
2710                       'Alphabetical sorting problem.')
2711
2712     if error_message:
2713         if file_extension == 'h':
2714             error(line_number, 'build/include_order', 4,
2715                   '%s Should be: alphabetically sorted.' %
2716                   error_message)
2717         else:
2718             error(line_number, 'build/include_order', 4,
2719                   '%s Should be: config.h, primary header, blank line, and then alphabetically sorted.' %
2720                   error_message)
2721
2722
2723 def check_language(filename, clean_lines, line_number, file_extension, include_state,
2724                    file_state, error):
2725     """Checks rules from the 'C++ language rules' section of cppguide.html.
2726
2727     Some of these rules are hard to test (function overloading, using
2728     uint32 inappropriately), but we do the best we can.
2729
2730     Args:
2731       filename: The name of the current file.
2732       clean_lines: A CleansedLines instance containing the file.
2733       line_number: The number of the line to check.
2734       file_extension: The extension (without the dot) of the filename.
2735       include_state: An _IncludeState instance in which the headers are inserted.
2736       file_state: A _FileState instance which maintains information about
2737                   the state of things in the file.
2738       error: The function to call with any errors found.
2739     """
2740     # If the line is empty or consists of entirely a comment, no need to
2741     # check it.
2742     line = clean_lines.elided[line_number]
2743     if not line:
2744         return
2745
2746     matched = _RE_PATTERN_INCLUDE.search(line)
2747     if matched:
2748         check_include_line(filename, file_extension, clean_lines, line_number, include_state, error)
2749         return
2750
2751     # FIXME: figure out if they're using default arguments in fn proto.
2752
2753     # Check to see if they're using an conversion function cast.
2754     # I just try to capture the most common basic types, though there are more.
2755     # Parameterless conversion functions, such as bool(), are allowed as they are
2756     # probably a member operator declaration or default constructor.
2757     matched = search(
2758         r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line)
2759     if matched:
2760         # gMock methods are defined using some variant of MOCK_METHODx(name, type)
2761         # where type may be float(), int(string), etc.  Without context they are
2762         # virtually indistinguishable from int(x) casts.
2763         if not match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line):
2764             error(line_number, 'readability/casting', 4,
2765                   'Using deprecated casting style.  '
2766                   'Use static_cast<%s>(...) instead' %
2767                   matched.group(1))
2768
2769     check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number],
2770                        'static_cast',
2771                        r'\((int|float|double|bool|char|u?int(16|32|64))\)',
2772                        error)
2773     # This doesn't catch all cases.  Consider (const char * const)"hello".
2774     check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number],
2775                        'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
2776
2777     # In addition, we look for people taking the address of a cast.  This
2778     # is dangerous -- casts can assign to temporaries, so the pointer doesn't
2779     # point where you think.
2780     if search(
2781         r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line):
2782         error(line_number, 'runtime/casting', 4,
2783               ('Are you taking an address of a cast?  '
2784                'This is dangerous: could be a temp var.  '
2785                'Take the address before doing the cast, rather than after'))
2786
2787     # Check for people declaring static/global STL strings at the top level.
2788     # This is dangerous because the C++ language does not guarantee that
2789     # globals with constructors are initialized before the first access.
2790     matched = match(
2791         r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
2792         line)
2793     # Make sure it's not a function.
2794     # Function template specialization looks like: "string foo<Type>(...".
2795     # Class template definitions look like: "string Foo<Type>::Method(...".
2796     if matched and not match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)',
2797                              matched.group(3)):
2798         error(line_number, 'runtime/string', 4,
2799               'For a static/global string constant, use a C style string instead: '
2800               '"%schar %s[]".' %
2801               (matched.group(1), matched.group(2)))
2802
2803     # Check that we're not using RTTI outside of testing code.
2804     if search(r'\bdynamic_cast<', line):
2805         error(line_number, 'runtime/rtti', 5,
2806               'Do not use dynamic_cast<>.  If you need to cast within a class '
2807               "hierarchy, use static_cast<> to upcast.  Google doesn't support "
2808               'RTTI.')
2809
2810     if search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
2811         error(line_number, 'runtime/init', 4,
2812               'You seem to be initializing a member variable with itself.')
2813
2814     if file_extension == 'h':
2815         # FIXME: check that 1-arg constructors are explicit.
2816         #        How to tell it's a constructor?
2817         #        (handled in check_for_non_standard_constructs for now)
2818         pass
2819
2820     # Check if people are using the verboten C basic types.  The only exception
2821     # we regularly allow is "unsigned short port" for port.
2822     if search(r'\bshort port\b', line):
2823         if not search(r'\bunsigned short port\b', line):
2824             error(line_number, 'runtime/int', 4,
2825                   'Use "unsigned short" for ports, not "short"')
2826
2827     # When snprintf is used, the second argument shouldn't be a literal.
2828     matched = search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
2829     if matched:
2830         error(line_number, 'runtime/printf', 3,
2831               'If you can, use sizeof(%s) instead of %s as the 2nd arg '
2832               'to snprintf.' % (matched.group(1), matched.group(2)))
2833
2834     # Check if some verboten C functions are being used.
2835     if search(r'\bsprintf\b', line):
2836         error(line_number, 'runtime/printf', 5,
2837               'Never use sprintf.  Use snprintf instead.')
2838     matched = search(r'\b(strcpy|strcat)\b', line)
2839     if matched:
2840         error(line_number, 'runtime/printf', 4,
2841               'Almost always, snprintf is better than %s' % matched.group(1))
2842
2843     if search(r'\bsscanf\b', line):
2844         error(line_number, 'runtime/printf', 1,
2845               'sscanf can be ok, but is slow and can overflow buffers.')
2846
2847     # Check for suspicious usage of "if" like
2848     # } if (a == b) {
2849     if search(r'\}\s*if\s*\(', line):
2850         error(line_number, 'readability/braces', 4,
2851               'Did you mean "else if"? If not, start a new line for "if".')
2852
2853     # Check for potential format string bugs like printf(foo).
2854     # We constrain the pattern not to pick things like DocidForPrintf(foo).
2855     # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
2856     matched = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I)
2857     if matched:
2858         error(line_number, 'runtime/printf', 4,
2859               'Potential format string bug. Do %s("%%s", %s) instead.'
2860               % (matched.group(1), matched.group(2)))
2861
2862     # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
2863     matched = search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
2864     if matched and not match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", matched.group(2)):
2865         error(line_number, 'runtime/memset', 4,
2866               'Did you mean "memset(%s, 0, %s)"?'
2867               % (matched.group(1), matched.group(2)))
2868
2869     # Detect variable-length arrays.
2870     matched = match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
2871     if (matched and matched.group(2) != 'return' and matched.group(2) != 'delete' and
2872         matched.group(3).find(']') == -1):
2873         # Split the size using space and arithmetic operators as delimiters.
2874         # If any of the resulting tokens are not compile time constants then
2875         # report the error.
2876         tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', matched.group(3))
2877         is_const = True
2878         skip_next = False
2879         for tok in tokens:
2880             if skip_next:
2881                 skip_next = False
2882                 continue
2883
2884             if search(r'sizeof\(.+\)', tok):
2885                 continue
2886             if search(r'arraysize\(\w+\)', tok):
2887                 continue
2888
2889             tok = tok.lstrip('(')
2890             tok = tok.rstrip(')')
2891             if not tok:
2892                 continue
2893             if match(r'\d+', tok):
2894                 continue
2895             if match(r'0[xX][0-9a-fA-F]+', tok):
2896                 continue
2897             if match(r'k[A-Z0-9]\w*', tok):
2898                 continue
2899             if match(r'(.+::)?k[A-Z0-9]\w*', tok):
2900                 continue
2901             if match(r'(.+::)?[A-Z][A-Z0-9_]*', tok):
2902                 continue
2903             # A catch all for tricky sizeof cases, including 'sizeof expression',
2904             # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
2905             # requires skipping the next token becasue we split on ' ' and '*'.
2906             if tok.startswith('sizeof'):
2907                 skip_next = True
2908                 continue
2909             is_const = False
2910             break
2911         if not is_const:
2912             error(line_number, 'runtime/arrays', 1,
2913                   'Do not use variable-length arrays.  Use an appropriately named '
2914                   "('k' followed by CamelCase) compile-time constant for the size.")
2915
2916     # Check for use of unnamed namespaces in header files.  Registration
2917     # macros are typically OK, so we allow use of "namespace {" on lines
2918     # that end with backslashes.
2919     if (file_extension == 'h'
2920         and search(r'\bnamespace\s*{', line)
2921         and line[-1] != '\\'):
2922         error(line_number, 'build/namespaces', 4,
2923               'Do not use unnamed namespaces in header files.  See '
2924               'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
2925               ' for more information.')
2926
2927     # Check for plain bitfields declared without either "singed" or "unsigned".
2928     # Most compilers treat such bitfields as signed, but there are still compilers like
2929     # RVCT 4.0 that use unsigned by default.
2930     matched = re.match(r'\s*((const|mutable)\s+)?(char|(short(\s+int)?)|int|long(\s+(long|int))?)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;', line)
2931     if matched:
2932         error(line_number, 'runtime/bitfields', 5,
2933               'Please declare integral type bitfields with either signed or unsigned.')
2934
2935     check_identifier_name_in_declaration(filename, line_number, line, file_state, error)
2936
2937
2938 def check_identifier_name_in_declaration(filename, line_number, line, file_state, error):
2939     """Checks if identifier names contain any underscores.
2940
2941     As identifiers in libraries we are using have a bunch of
2942     underscores, we only warn about the declarations of identifiers
2943     and don't check use of identifiers.
2944
2945     Args:
2946       filename: The name of the current file.
2947       line_number: The number of the line to check.
2948       line: The line of code to check.
2949       file_state: A _FileState instance which maintains information about
2950                   the state of things in the file.
2951       error: The function to call with any errors found.
2952     """
2953     # We don't check a return statement.
2954     if match(r'\s*(return|delete)\b', line):
2955         return
2956
2957     # Basically, a declaration is a type name followed by whitespaces
2958     # followed by an identifier. The type name can be complicated
2959     # due to type adjectives and templates. We remove them first to
2960     # simplify the process to find declarations of identifiers.
2961
2962     # Convert "long long", "long double", and "long long int" to
2963     # simple types, but don't remove simple "long".
2964     line = sub(r'long (long )?(?=long|double|int)', '', line)
2965     # Convert unsigned/signed types to simple types, too.
2966     line = sub(r'(unsigned|signed) (?=char|short|int|long)', '', line)
2967     line = sub(r'\b(inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line)
2968
2969     # Remove "new" and "new (expr)" to simplify, too.
2970     line = sub(r'new\s*(\([^)]*\))?', '', line)
2971
2972     # Remove all template parameters by removing matching < and >.
2973     # Loop until no templates are removed to remove nested templates.
2974     while True:
2975         line, number_of_replacements = subn(r'<([\w\s:]|::)+\s*[*&]*\s*>', '', line)
2976         if not number_of_replacements:
2977             break
2978
2979     # Declarations of local variables can be in condition expressions
2980     # of control flow statements (e.g., "if (RenderObject* p = o->parent())").
2981     # We remove the keywords and the first parenthesis.
2982     #
2983     # Declarations in "while", "if", and "switch" are different from
2984     # other declarations in two aspects:
2985     #
2986     # - There can be only one declaration between the parentheses.
2987     #   (i.e., you cannot write "if (int i = 0, j = 1) {}")
2988     # - The variable must be initialized.
2989     #   (i.e., you cannot write "if (int i) {}")
2990     #
2991     # and we will need different treatments for them.
2992     line = sub(r'^\s*for\s*\(', '', line)
2993     line, control_statement = subn(r'^\s*(while|else if|if|switch)\s*\(', '', line)
2994
2995     # Detect variable and functions.
2996     type_regexp = r'\w([\w]|\s*[*&]\s*|::)+'
2997     identifier_regexp = r'(?P<identifier>[\w:]+)'
2998     maybe_bitfield_regexp = r'(:\s*\d+\s*)?'
2999     character_after_identifier_regexp = r'(?P<character_after_identifier>[[;()=,])(?!=)'
3000     declaration_without_type_regexp = r'\s*' + identifier_regexp + r'\s*' + maybe_bitfield_regexp + character_after_identifier_regexp
3001     declaration_with_type_regexp = r'\s*' + type_regexp + r'\s' + declaration_without_type_regexp
3002     is_function_arguments = False
3003     number_of_identifiers = 0
3004     while True:
3005         # If we are seeing the first identifier or arguments of a
3006         # function, there should be a type name before an identifier.
3007         if not number_of_identifiers or is_function_arguments:
3008             declaration_regexp = declaration_with_type_regexp
3009         else:
3010             declaration_regexp = declaration_without_type_regexp
3011
3012         matched = match(declaration_regexp, line)
3013         if not matched:
3014             return
3015         identifier = matched.group('identifier')
3016         character_after_identifier = matched.group('character_after_identifier')
3017
3018         # If we removed a non-for-control statement, the character after
3019         # the identifier should be '='. With this rule, we can avoid
3020         # warning for cases like "if (val & INT_MAX) {".
3021         if control_statement and character_after_identifier != '=':
3022             return
3023
3024         is_function_arguments = is_function_arguments or character_after_identifier == '('
3025
3026         # Remove "m_" and "s_" to allow them.
3027         modified_identifier = sub(r'(^|(?<=::))[ms]_', '', identifier)
3028         if not file_state.is_objective_c() and modified_identifier.find('_') >= 0:
3029             # Various exceptions to the rule: JavaScript op codes functions, const_iterator.
3030             if (not (filename.find('JavaScriptCore') >= 0 and modified_identifier.find('op_') >= 0)
3031                 and not modified_identifier.startswith('tst_')
3032                 and not modified_identifier.startswith('webkit_dom_object_')
3033                 and not modified_identifier.startswith('NPN_')
3034                 and not modified_identifier.startswith('NPP_')
3035                 and not modified_identifier.startswith('NP_')
3036                 and not modified_identifier.startswith('qt_')
3037                 and not modified_identifier.startswith('cairo_')
3038                 and not modified_identifier.find('::qt_') >= 0
3039                 and not modified_identifier == "const_iterator"
3040                 and not modified_identifier == "vm_throw"):
3041                 error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.")
3042
3043         # Check for variables named 'l', these are too easy to confuse with '1' in some fonts
3044         if modified_identifier == 'l':
3045             error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use the single letter 'l' as an identifier name.")
3046
3047         # There can be only one declaration in non-for-control statements.
3048         if control_statement:
3049             return
3050         # We should continue checking if this is a function
3051         # declaration because we need to check its arguments.
3052         # Also, we need to check multiple declarations.
3053         if character_after_identifier != '(' and character_after_identifier != ',':
3054             return
3055
3056         number_of_identifiers += 1
3057         line = line[matched.end():]
3058
3059 def check_c_style_cast(line_number, line, raw_line, cast_type, pattern,
3060                        error):
3061     """Checks for a C-style cast by looking for the pattern.
3062
3063     This also handles sizeof(type) warnings, due to similarity of content.
3064
3065     Args:
3066       line_number: The number of the line to check.
3067       line: The line of code to check.
3068       raw_line: The raw line of code to check, with comments.
3069       cast_type: The string for the C++ cast to recommend.  This is either
3070                  reinterpret_cast or static_cast, depending.
3071       pattern: The regular expression used to find C-style casts.
3072       error: The function to call with any errors found.
3073     """
3074     matched = search(pattern, line)
3075     if not matched:
3076         return
3077
3078     # e.g., sizeof(int)
3079     sizeof_match = match(r'.*sizeof\s*$', line[0:matched.start(1) - 1])
3080     if sizeof_match:
3081         error(line_number, 'runtime/sizeof', 1,
3082               'Using sizeof(type).  Use sizeof(varname) instead if possible')
3083         return
3084
3085     remainder = line[matched.end(0):]
3086
3087     # The close paren is for function pointers as arguments to a function.
3088     # eg, void foo(void (*bar)(int));
3089     # The semicolon check is a more basic function check; also possibly a
3090     # function pointer typedef.
3091     # eg, void foo(int); or void foo(int) const;
3092     # The equals check is for function pointer assignment.
3093     # eg, void *(*foo)(int) = ...
3094     #
3095     # Right now, this will only catch cases where there's a single argument, and
3096     # it's unnamed.  It should probably be expanded to check for multiple
3097     # arguments with some unnamed.
3098     function_match = match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder)
3099     if function_match:
3100         if (not function_match.group(3)
3101             or function_match.group(3) == ';'
3102             or raw_line.find('/*') < 0):
3103             error(line_number, 'readability/function', 3,
3104                   'All parameters should be named in a function')
3105         return
3106
3107     # At this point, all that should be left is actual casts.
3108     error(line_number, 'readability/casting', 4,
3109           'Using C-style cast.  Use %s<%s>(...) instead' %
3110           (cast_type, matched.group(1)))
3111
3112
3113 _HEADERS_CONTAINING_TEMPLATES = (
3114     ('<deque>', ('deque',)),
3115     ('<functional>', ('unary_function', 'binary_function',
3116                       'plus', 'minus', 'multiplies', 'divides', 'modulus',
3117                       'negate',
3118                       'equal_to', 'not_equal_to', 'greater', 'less',
3119                       'greater_equal', 'less_equal',
3120                       'logical_and', 'logical_or', 'logical_not',
3121                       'unary_negate', 'not1', 'binary_negate', 'not2',
3122                       'bind1st', 'bind2nd',
3123                       'pointer_to_unary_function',
3124                       'pointer_to_binary_function',
3125                       'ptr_fun',
3126                       'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t',
3127                       'mem_fun_ref_t',
3128                       'const_mem_fun_t', 'const_mem_fun1_t',
3129                       'const_mem_fun_ref_t', 'const_mem_fun1_ref_t',
3130                       'mem_fun_ref',
3131                      )),
3132     ('<limits>', ('numeric_limits',)),
3133     ('<list>', ('list',)),
3134     ('<map>', ('map', 'multimap',)),
3135     ('<memory>', ('allocator',)),
3136     ('<queue>', ('queue', 'priority_queue',)),
3137     ('<set>', ('set', 'multiset',)),
3138     ('<stack>', ('stack',)),
3139     ('<string>', ('char_traits', 'basic_string',)),
3140     ('<utility>', ('pair',)),
3141     ('<vector>', ('vector',)),
3142
3143     # gcc extensions.
3144     # Note: std::hash is their hash, ::hash is our hash
3145     ('<hash_map>', ('hash_map', 'hash_multimap',)),
3146     ('<hash_set>', ('hash_set', 'hash_multiset',)),
3147     ('<slist>', ('slist',)),
3148     )
3149
3150 _HEADERS_ACCEPTED_BUT_NOT_PROMOTED = {
3151     # We can trust with reasonable confidence that map gives us pair<>, too.
3152     'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap')
3153 }
3154
3155 _RE_PATTERN_STRING = re.compile(r'\bstring\b')
3156
3157 _re_pattern_algorithm_header = []
3158 for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap',
3159                   'transform'):
3160     # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or
3161     # type::max().
3162     _re_pattern_algorithm_header.append(
3163         (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
3164          _template,
3165          '<algorithm>'))
3166
3167 _re_pattern_templates = []
3168 for _header, _templates in _HEADERS_CONTAINING_TEMPLATES:
3169     for _template in _templates:
3170         _re_pattern_templates.append(
3171             (re.compile(r'(\<|\b)' + _template + r'\s*\<'),
3172              _template + '<>',
3173              _header))
3174
3175
3176 def files_belong_to_same_module(filename_cpp, filename_h):
3177     """Check if these two filenames belong to the same module.
3178
3179     The concept of a 'module' here is a as follows:
3180     foo.h, foo-inl.h, foo.cpp, foo_test.cpp and foo_unittest.cpp belong to the
3181     same 'module' if they are in the same directory.
3182     some/path/public/xyzzy and some/path/internal/xyzzy are also considered
3183     to belong to the same module here.
3184
3185     If the filename_cpp contains a longer path than the filename_h, for example,
3186     '/absolute/path/to/base/sysinfo.cpp', and this file would include
3187     'base/sysinfo.h', this function also produces the prefix needed to open the
3188     header. This is used by the caller of this function to more robustly open the
3189     header file. We don't have access to the real include paths in this context,
3190     so we need this guesswork here.
3191
3192     Known bugs: tools/base/bar.cpp and base/bar.h belong to the same module
3193     according to this implementation. Because of this, this function gives
3194     some false positives. This should be sufficiently rare in practice.
3195
3196     Args:
3197       filename_cpp: is the path for the .cpp file
3198       filename_h: is the path for the header path
3199
3200     Returns:
3201       Tuple with a bool and a string:
3202       bool: True if filename_cpp and filename_h belong to the same module.
3203       string: the additional prefix needed to open the header file.
3204     """
3205
3206     if not filename_cpp.endswith('.cpp'):
3207         return (False, '')
3208     filename_cpp = filename_cpp[:-len('.cpp')]
3209     if filename_cpp.endswith('_unittest'):
3210         filename_cpp = filename_cpp[:-len('_unittest')]
3211     elif filename_cpp.endswith('_test'):
3212         filename_cpp = filename_cpp[:-len('_test')]
3213     filename_cpp = filename_cpp.replace('/public/', '/')
3214     filename_cpp = filename_cpp.replace('/internal/', '/')
3215
3216     if not filename_h.endswith('.h'):
3217         return (False, '')
3218     filename_h = filename_h[:-len('.h')]
3219     if filename_h.endswith('-inl'):
3220         filename_h = filename_h[:-len('-inl')]
3221     filename_h = filename_h.replace('/public/', '/')
3222     filename_h = filename_h.replace('/internal/', '/')
3223
3224     files_belong_to_same_module = filename_cpp.endswith(filename_h)
3225     common_path = ''
3226     if files_belong_to_same_module:
3227         common_path = filename_cpp[:-len(filename_h)]
3228     return files_belong_to_same_module, common_path
3229
3230
3231 def update_include_state(filename, include_state, io=codecs):
3232     """Fill up the include_state with new includes found from the file.
3233
3234     Args:
3235       filename: the name of the header to read.
3236       include_state: an _IncludeState instance in which the headers are inserted.
3237       io: The io factory to use to read the file. Provided for testability.
3238
3239     Returns:
3240       True if a header was succesfully added. False otherwise.
3241     """
3242     io = _unit_test_config.get(INCLUDE_IO_INJECTION_KEY, codecs)
3243     header_file = None
3244     try:
3245         header_file = io.open(filename, 'r', 'utf8', 'replace')
3246     except IOError:
3247         return False
3248     line_number = 0
3249     for line in header_file:
3250         line_number += 1
3251         clean_line = cleanse_comments(line)
3252         matched = _RE_PATTERN_INCLUDE.search(clean_line)
3253         if matched:
3254             include = matched.group(2)
3255             # The value formatting is cute, but not really used right now.
3256             # What matters here is that the key is in include_state.
3257             include_state.setdefault(include, '%s:%d' % (filename, line_number))
3258     return True
3259
3260
3261 def check_for_include_what_you_use(filename, clean_lines, include_state, error):
3262     """Reports for missing stl includes.
3263
3264     This function will output warnings to make sure you are including the headers
3265     necessary for the stl containers and functions that you use. We only give one
3266     reason to include a header. For example, if you use both equal_to<> and
3267     less<> in a .h file, only one (the latter in the file) of these will be
3268     reported as a reason to include the <functional>.
3269
3270     Args:
3271       filename: The name of the current file.
3272       clean_lines: A CleansedLines instance containing the file.
3273       include_state: An _IncludeState instance.
3274       error: The function to call with any errors found.
3275     """
3276     required = {}  # A map of header name to line_number and the template entity.
3277         # Example of required: { '<functional>': (1219, 'less<>') }
3278
3279     for line_number in xrange(clean_lines.num_lines()):
3280         line = clean_lines.elided[line_number]
3281         if not line or line[0] == '#':
3282             continue
3283
3284         # String is special -- it is a non-templatized type in STL.
3285         if _RE_PATTERN_STRING.search(line):
3286             required['<string>'] = (line_number, 'string')
3287
3288         for pattern, template, header in _re_pattern_algorithm_header:
3289             if pattern.search(line):
3290                 required[header] = (line_number, template)
3291
3292         # The following function is just a speed up, no semantics are changed.
3293         if not '<' in line:  # Reduces the cpu time usage by skipping lines.
3294             continue
3295
3296         for pattern, template, header in _re_pattern_templates:
3297             if pattern.search(line):
3298                 required[header] = (line_number, template)
3299
3300     # The policy is that if you #include something in foo.h you don't need to
3301     # include it again in foo.cpp. Here, we will look at possible includes.
3302     # Let's copy the include_state so it is only messed up within this function.
3303     include_state = include_state.copy()
3304
3305     # Did we find the header for this file (if any) and succesfully load it?
3306     header_found = False
3307
3308     # Use the absolute path so that matching works properly.
3309     abs_filename = os.path.abspath(filename)
3310
3311     # For Emacs's flymake.
3312     # If cpp_style is invoked from Emacs's flymake, a temporary file is generated
3313     # by flymake and that file name might end with '_flymake.cpp'. In that case,
3314     # restore original file name here so that the corresponding header file can be
3315     # found.
3316     # e.g. If the file name is 'foo_flymake.cpp', we should search for 'foo.h'
3317     # instead of 'foo_flymake.h'
3318     abs_filename = re.sub(r'_flymake\.cpp$', '.cpp', abs_filename)
3319
3320     # include_state is modified during iteration, so we iterate over a copy of
3321     # the keys.
3322     for header in include_state.keys():  #NOLINT
3323         (same_module, common_path) = files_belong_to_same_module(abs_filename, header)
3324         fullpath = common_path + header
3325         if same_module and update_include_state(fullpath, include_state):
3326             header_found = True
3327
3328     # If we can't find the header file for a .cpp, assume it's because we don't
3329     # know where to look. In that case we'll give up as we're not sure they
3330     # didn't include it in the .h file.
3331     # FIXME: Do a better job of finding .h files so we are confident that
3332     #        not having the .h file means there isn't one.
3333     if filename.endswith('.cpp') and not header_found:
3334         return
3335
3336     # All the lines have been processed, report the errors found.
3337     for required_header_unstripped in required:
3338         template = required[required_header_unstripped][1]
3339         if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED:
3340             headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template]
3341             if [True for header in headers if header in include_state]:
3342                 continue
3343         if required_header_unstripped.strip('<>"') not in include_state:
3344             error(required[required_header_unstripped][0],
3345                   'build/include_what_you_use', 4,
3346                   'Add #include ' + required_header_unstripped + ' for ' + template)
3347
3348
3349 def process_line(filename, file_extension,
3350                  clean_lines, line, include_state, function_state,
3351                  class_state, file_state, error):
3352     """Processes a single line in the file.
3353
3354     Args:
3355       filename: Filename of the file that is being processed.
3356       file_extension: The extension (dot not included) of the file.
3357       clean_lines: An array of strings, each representing a line of the file,
3358                    with comments stripped.
3359       line: Number of line being processed.
3360       include_state: An _IncludeState instance in which the headers are inserted.
3361       function_state: A _FunctionState instance which counts function lines, etc.
3362       class_state: A _ClassState instance which maintains information about
3363                    the current stack of nested class declarations being parsed.
3364       file_state: A _FileState instance which maintains information about
3365                   the state of things in the file.
3366       error: A callable to which errors are reported, which takes arguments:
3367              line number, error level, and message
3368
3369     """
3370     raw_lines = clean_lines.raw_lines
3371     detect_functions(clean_lines, line, function_state, error)
3372     check_for_function_lengths(clean_lines, line, function_state, error)
3373     if search(r'\bNOLINT\b', raw_lines[line]):  # ignore nolint lines
3374         return
3375     check_function_definition(filename, file_extension, clean_lines, line, function_state, error)
3376     check_pass_ptr_usage(clean_lines, line, function_state, error)
3377     check_for_multiline_comments_and_strings(clean_lines, line, error)
3378     check_style(clean_lines, line, file_extension, class_state, file_state, error)
3379     check_language(filename, clean_lines, line, file_extension, include_state,
3380                    file_state, error)
3381     check_for_non_standard_constructs(clean_lines, line, class_state, error)
3382     check_posix_threading(clean_lines, line, error)
3383     check_invalid_increment(clean_lines, line, error)
3384
3385
3386 def _process_lines(filename, file_extension, lines, error, min_confidence):
3387     """Performs lint checks and reports any errors to the given error function.
3388
3389     Args:
3390       filename: Filename of the file that is being processed.
3391       file_extension: The extension (dot not included) of the file.
3392       lines: An array of strings, each representing a line of the file, with the
3393              last element being empty if the file is termined with a newline.
3394       error: A callable to which errors are reported, which takes 4 arguments:
3395     """
3396     lines = (['// marker so line numbers and indices both start at 1'] + lines +
3397              ['// marker so line numbers end in a known way'])
3398
3399     include_state = _IncludeState()
3400     function_state = _FunctionState(min_confidence)
3401     class_state = _ClassState()
3402
3403     check_for_copyright(lines, error)
3404
3405     if file_extension == 'h':
3406         check_for_header_guard(filename, lines, error)
3407
3408     remove_multi_line_comments(lines, error)
3409     clean_lines = CleansedLines(lines)
3410     file_state = _FileState(clean_lines, file_extension)
3411     for line in xrange(clean_lines.num_lines()):
3412         process_line(filename, file_extension, clean_lines, line,
3413                      include_state, function_state, class_state, file_state, error)
3414     class_state.check_finished(error)
3415
3416     check_for_include_what_you_use(filename, clean_lines, include_state, error)
3417
3418     # We check here rather than inside process_line so that we see raw
3419     # lines rather than "cleaned" lines.
3420     check_for_unicode_replacement_characters(lines, error)
3421
3422     check_for_new_line_at_eof(lines, error)
3423
3424
3425 class CppChecker(object):
3426
3427     """Processes C++ lines for checking style."""
3428
3429     # This list is used to--
3430     #
3431     # (1) generate an explicit list of all possible categories,
3432     # (2) unit test that all checked categories have valid names, and
3433     # (3) unit test that all categories are getting unit tested.
3434     #
3435     categories = set([
3436         'build/class',
3437         'build/deprecated',
3438         'build/endif_comment',
3439         'build/forward_decl',
3440         'build/header_guard',
3441         'build/include',
3442         'build/include_order',
3443         'build/include_what_you_use',
3444         'build/namespaces',
3445         'build/printf_format',
3446         'build/storage_class',
3447         'build/using_std',
3448         'legal/copyright',
3449         'readability/braces',
3450         'readability/casting',
3451         'readability/check',
3452         'readability/comparison_to_zero',
3453         'readability/constructors',
3454         'readability/control_flow',
3455         'readability/fn_size',
3456         'readability/function',
3457         'readability/multiline_comment',
3458         'readability/multiline_string',
3459         'readability/parameter_name',
3460         'readability/naming',
3461         'readability/null',
3462         'readability/pass_ptr',
3463         'readability/streams',
3464         'readability/todo',
3465         'readability/utf8',
3466         'readability/webkit_api',
3467         'runtime/arrays',
3468         'runtime/bitfields',
3469         'runtime/casting',
3470         'runtime/explicit',
3471         'runtime/init',
3472         'runtime/int',
3473         'runtime/invalid_increment',
3474         'runtime/max_min_macros',
3475         'runtime/memset',
3476         'runtime/printf',
3477         'runtime/printf_format',
3478         'runtime/references',
3479         'runtime/rtti',
3480         'runtime/sizeof',
3481         'runtime/string',
3482         'runtime/threadsafe_fn',
3483         'runtime/virtual',
3484         'whitespace/blank_line',
3485         'whitespace/braces',
3486         'whitespace/comma',
3487         'whitespace/comments',
3488         'whitespace/declaration',
3489         'whitespace/end_of_line',
3490         'whitespace/ending_newline',
3491         'whitespace/indent',
3492         'whitespace/labels',
3493         'whitespace/line_length',
3494         'whitespace/newline',
3495         'whitespace/operators',
3496         'whitespace/parens',
3497         'whitespace/semicolon',
3498         'whitespace/tab',
3499         'whitespace/todo',
3500         ])
3501
3502     def __init__(self, file_path, file_extension, handle_style_error,
3503                  min_confidence):
3504         """Create a CppChecker instance.
3505
3506         Args:
3507           file_extension: A string that is the file extension, without
3508                           the leading dot.
3509
3510         """
3511         self.file_extension = file_extension
3512         self.file_path = file_path
3513         self.handle_style_error = handle_style_error
3514         self.min_confidence = min_confidence
3515
3516     # Useful for unit testing.
3517     def __eq__(self, other):
3518         """Return whether this CppChecker instance is equal to another."""
3519         if self.file_extension != other.file_extension:
3520             return False
3521         if self.file_path != other.file_path:
3522             return False
3523         if self.handle_style_error != other.handle_style_error:
3524             return False
3525         if self.min_confidence != other.min_confidence:
3526             return False
3527
3528         return True
3529
3530     # Useful for unit testing.
3531     def __ne__(self, other):
3532         # Python does not automatically deduce __ne__() from __eq__().
3533         return not self.__eq__(other)
3534
3535     def check(self, lines):
3536         _process_lines(self.file_path, self.file_extension, lines,
3537                        self.handle_style_error, self.min_confidence)
3538
3539
3540 # FIXME: Remove this function (requires refactoring unit tests).
3541 def process_file_data(filename, file_extension, lines, error, min_confidence, unit_test_config):
3542     global _unit_test_config
3543     _unit_test_config = unit_test_config
3544     checker = CppChecker(filename, file_extension, error, min_confidence)
3545     checker.check(lines)
3546     _unit_test_config = {}