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