10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#!/usr/bin/python 20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# -*- coding: utf-8 -*- 30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# 4cad810f21b803229eb11403f9209855525a25d57Steve Block# Copyright (C) 2009, 2010 Google Inc. All rights reserved. 50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Copyright (C) 2009 Torch Mobile Inc. 6231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block# Copyright (C) 2009 Apple Inc. All rights reserved. 7d0825bca7fe65beaee391d30da42e937db621564Steve Block# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) 80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# 90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Redistribution and use in source and binary forms, with or without 100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# modification, are permitted provided that the following conditions are 110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# met: 120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# 130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# * Redistributions of source code must retain the above copyright 140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# notice, this list of conditions and the following disclaimer. 150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# * Redistributions in binary form must reproduce the above 160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# copyright notice, this list of conditions and the following disclaimer 170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# in the documentation and/or other materials provided with the 180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# distribution. 190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# * Neither the name of Google Inc. nor the names of its 200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# contributors may be used to endorse or promote products derived from 210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# this software without specific prior written permission. 220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# 230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# This is the modified version of Google's cpplint. The original code is 360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py 370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 38d0825bca7fe65beaee391d30da42e937db621564Steve Block"""Support for check-webkit-style.""" 390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport codecs 410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport math # for log 420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport os 430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport os.path 440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport re 450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport sre_compile 460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport string 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport sys 480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochimport unicodedata 490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 50cad810f21b803229eb11403f9209855525a25d57Steve Blockfrom webkitpy.common.memoized import memoized 51cad810f21b803229eb11403f9209855525a25d57Steve Block 52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# The key to use to provide a class to fake loading a header file. 53f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochINCLUDE_IO_INJECTION_KEY = 'include_header_io' 540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Headers that we consider STL headers. 560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_STL_HEADERS = frozenset([ 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', 580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', 590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', 600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', 610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', 620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'utility', 'vector', 'vector.h', 630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ]) 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Non-STL C++ system headers. 670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CPP_HEADERS = frozenset([ 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', 690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', 710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', 720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', 730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', 740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h', 750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', 760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h', 770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h', 780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', 790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', 800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', 810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ]) 820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Assertion macros. These are defined in base/logging.h and 850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# testing/base/gunit.h. Note that the _M versions need to come first 860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# for substring matching to work. 870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CHECK_MACROS = [ 880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'DCHECK', 'CHECK', 890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'EXPECT_TRUE_M', 'EXPECT_TRUE', 900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ASSERT_TRUE_M', 'ASSERT_TRUE', 910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'EXPECT_FALSE_M', 'EXPECT_FALSE', 920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ASSERT_FALSE_M', 'ASSERT_FALSE', 930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ] 940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE 960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) 970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor op, replacement in [('==', 'EQ'), ('!=', 'NE'), 990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('>=', 'GE'), ('>', 'GT'), 1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<=', 'LE'), ('<', 'LT')]: 1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement 1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement 1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement 1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement 1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement 1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement 1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), 1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('>=', 'LT'), ('>', 'LE'), 1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<=', 'GT'), ('<', 'GE')]: 1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement 1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement 1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement 1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement 1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# These constants define types of headers for use with 1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _IncludeState.check_next_include_order(). 1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CONFIG_HEADER = 0 1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_PRIMARY_HEADER = 1 1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_OTHER_HEADER = 2 122d0825bca7fe65beaee391d30da42e937db621564Steve Block_MOC_HEADER = 3 1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# A dictionary of items customize behavior for unit test. For example, 126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# INCLUDE_IO_INJECTION_KEY allows providing a custom io class which allows 127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# for faking a header file. 128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch_unit_test_config = {} 129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# The regexp compilation caching is inlined in all regexp functions for 132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# performance reasons; factoring it out into a separate function turns out 133643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# to be noticeably expensive. 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_regexp_compile_cache = {} 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef match(pattern, s): 1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Matches the string with the pattern, caching the compiled regexp.""" 1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not pattern in _regexp_compile_cache: 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _regexp_compile_cache[pattern].match(s) 1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef search(pattern, s): 1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Searches the string for the pattern, caching the compiled regexp.""" 1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not pattern in _regexp_compile_cache: 1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _regexp_compile_cache[pattern].search(s) 1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 151643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdef sub(pattern, replacement, s): 152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Substitutes occurrences of a pattern, caching the compiled regexp.""" 153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not pattern in _regexp_compile_cache: 154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return _regexp_compile_cache[pattern].sub(replacement, s) 156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 157643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 158643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdef subn(pattern, replacement, s): 159643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Substitutes occurrences of a pattern, caching the compiled regexp.""" 160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not pattern in _regexp_compile_cache: 161643ca7872b450ea4efacab6188849e5aac2ba161Steve Block _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 162643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return _regexp_compile_cache[pattern].subn(replacement, s) 163643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerdef iteratively_replace_matches_with_char(pattern, char_replacement, s): 1666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Returns the string with replacement done. 1676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Every character in the match is replaced with char. 1696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Due to the iterative nature, pattern should not match char or 1706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner there will be an infinite loop. 1716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Example: 1736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner pattern = r'<[^>]>' # template parameters 1746b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner char_replacement = '_' 1756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner s = 'A<B<C, D>>' 1766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Returns 'A_________' 1776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Args: 1796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner pattern: The regex to match. 1806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner char_replacement: The character to put in place of every 1816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner character of the match. 1826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner s: The string on which to do the replacements. 1836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Returns: 1856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner True, if the given line is blank. 1866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """ 1876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner while True: 1886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner matched = search(pattern, s) 1896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not matched: 1906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return s 1916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner start_match_index = matched.start(0) 1926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner end_match_index = matched.end(0) 1936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner match_length = end_match_index - start_match_index 1946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner s = s[:start_match_index] + char_replacement * match_length + s[end_match_index:] 1956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1972fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockdef _rfind_in_lines(regex, lines, start_position, not_found_position): 1982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Does a reverse find starting at start position and going backwards until 1992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block a match is found. 2002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Returns the position where the regex ended. 2022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """ 2032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # Put the regex in a group and proceed it with a greedy expression that 2042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # matches anything to ensure that we get the last possible match in a line. 2052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block last_in_line_regex = r'.*(' + regex + ')' 2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block current_row = start_position.row 2072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # Start with the given row and trim off everything past what may be matched. 2092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block current_line = lines[start_position.row][:start_position.column] 2102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block while True: 2112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block found_match = match(last_in_line_regex, current_line) 2122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if found_match: 2132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return Position(current_row, found_match.end(1)) 2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # A match was not found so continue backward. 2162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block current_row -= 1 2172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if current_row < 0: 2182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return not_found_position 2192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block current_line = lines[current_row] 2202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 222cad810f21b803229eb11403f9209855525a25d57Steve Blockdef _convert_to_lower_with_underscores(text): 223cad810f21b803229eb11403f9209855525a25d57Steve Block """Converts all text strings in camelCase or PascalCase to lowers with underscores.""" 224cad810f21b803229eb11403f9209855525a25d57Steve Block 225cad810f21b803229eb11403f9209855525a25d57Steve Block # First add underscores before any capital letter followed by a lower case letter 226cad810f21b803229eb11403f9209855525a25d57Steve Block # as long as it is in a word. 227cad810f21b803229eb11403f9209855525a25d57Steve Block # (This put an underscore before Password but not P and A in WPAPassword). 228cad810f21b803229eb11403f9209855525a25d57Steve Block text = sub(r'(?<=[A-Za-z0-9])([A-Z])(?=[a-z])', r'_\1', text) 229cad810f21b803229eb11403f9209855525a25d57Steve Block 230cad810f21b803229eb11403f9209855525a25d57Steve Block # Next add underscores before capitals at the end of words if it was 231cad810f21b803229eb11403f9209855525a25d57Steve Block # preceeded by lower case letter or number. 232cad810f21b803229eb11403f9209855525a25d57Steve Block # (This puts an underscore before A in isA but not A in CBA). 233cad810f21b803229eb11403f9209855525a25d57Steve Block text = sub(r'(?<=[a-z0-9])([A-Z])(?=\b)', r'_\1', text) 234cad810f21b803229eb11403f9209855525a25d57Steve Block 235cad810f21b803229eb11403f9209855525a25d57Steve Block # Next add underscores when you have a captial letter which is followed by a capital letter 236cad810f21b803229eb11403f9209855525a25d57Steve Block # but is not proceeded by one. (This puts an underscore before A in 'WordADay'). 237cad810f21b803229eb11403f9209855525a25d57Steve Block text = sub(r'(?<=[a-z0-9])([A-Z][A-Z_])', r'_\1', text) 238cad810f21b803229eb11403f9209855525a25d57Steve Block 239cad810f21b803229eb11403f9209855525a25d57Steve Block return text.lower() 240cad810f21b803229eb11403f9209855525a25d57Steve Block 241cad810f21b803229eb11403f9209855525a25d57Steve Block 242cad810f21b803229eb11403f9209855525a25d57Steve Block 243cad810f21b803229eb11403f9209855525a25d57Steve Blockdef _create_acronym(text): 244cad810f21b803229eb11403f9209855525a25d57Steve Block """Creates an acronym for the given text.""" 245cad810f21b803229eb11403f9209855525a25d57Steve Block # Removes all lower case letters except those starting words. 246cad810f21b803229eb11403f9209855525a25d57Steve Block text = sub(r'(?<!\b)[a-z]', '', text) 247cad810f21b803229eb11403f9209855525a25d57Steve Block return text.upper() 248cad810f21b803229eb11403f9209855525a25d57Steve Block 249cad810f21b803229eb11403f9209855525a25d57Steve Block 250d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef up_to_unmatched_closing_paren(s): 251d0825bca7fe65beaee391d30da42e937db621564Steve Block """Splits a string into two parts up to first unmatched ')'. 252d0825bca7fe65beaee391d30da42e937db621564Steve Block 253d0825bca7fe65beaee391d30da42e937db621564Steve Block Args: 254d0825bca7fe65beaee391d30da42e937db621564Steve Block s: a string which is a substring of line after '(' 255d0825bca7fe65beaee391d30da42e937db621564Steve Block (e.g., "a == (b + c))"). 256d0825bca7fe65beaee391d30da42e937db621564Steve Block 257d0825bca7fe65beaee391d30da42e937db621564Steve Block Returns: 258d0825bca7fe65beaee391d30da42e937db621564Steve Block A pair of strings (prefix before first unmatched ')', 25906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen remainder of s after first unmatched ')'), e.g., 260d0825bca7fe65beaee391d30da42e937db621564Steve Block up_to_unmatched_closing_paren("a == (b + c)) { ") 261d0825bca7fe65beaee391d30da42e937db621564Steve Block returns "a == (b + c)", " {". 262d0825bca7fe65beaee391d30da42e937db621564Steve Block Returns None, None if there is no unmatched ')' 263d0825bca7fe65beaee391d30da42e937db621564Steve Block 264d0825bca7fe65beaee391d30da42e937db621564Steve Block """ 265d0825bca7fe65beaee391d30da42e937db621564Steve Block i = 1 266d0825bca7fe65beaee391d30da42e937db621564Steve Block for pos, c in enumerate(s): 267d0825bca7fe65beaee391d30da42e937db621564Steve Block if c == '(': 268d0825bca7fe65beaee391d30da42e937db621564Steve Block i += 1 269d0825bca7fe65beaee391d30da42e937db621564Steve Block elif c == ')': 270d0825bca7fe65beaee391d30da42e937db621564Steve Block i -= 1 271d0825bca7fe65beaee391d30da42e937db621564Steve Block if i == 0: 272d0825bca7fe65beaee391d30da42e937db621564Steve Block return s[:pos], s[pos + 1:] 273d0825bca7fe65beaee391d30da42e937db621564Steve Block return None, None 274d0825bca7fe65beaee391d30da42e937db621564Steve Block 2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _IncludeState(dict): 2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Tracks line numbers for includes, and the order in which includes appear. 2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch As a dict, an _IncludeState object serves as a mapping between include 2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename and line number on which that file was included. 2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Call check_next_include_order() once for each header in the file, passing 2820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch in the type constants defined above. Calls in an illegal order will 2830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raise an _IncludeError with an appropriate error message. 2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # self._section will move monotonically through this set. If it ever 2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # needs to move backwards, check_next_include_order will raise an error. 2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _INITIAL_SECTION = 0 2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_SECTION = 1 2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_SECTION = 2 2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_SECTION = 3 2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _TYPE_NAMES = { 2940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_HEADER: 'WebCore config.h', 2950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_HEADER: 'header this file implements', 2960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_HEADER: 'other header', 297d0825bca7fe65beaee391d30da42e937db621564Steve Block _MOC_HEADER: 'moc file', 2980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _SECTION_NAMES = { 3000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _INITIAL_SECTION: "... nothing.", 3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_SECTION: "WebCore config.h.", 3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_SECTION: 'a header this file implements.', 3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_SECTION: 'other header.', 3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self): 3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch dict.__init__(self) 3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._INITIAL_SECTION 3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._visited_primary_section = False 3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.header_types = dict(); 3110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def visited_primary_section(self): 3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self._visited_primary_section 3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch def check_next_include_order(self, header_type, file_is_header, primary_header_exists): 3160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns a non-empty error message if the next header is out of order. 3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function also updates the internal state to be ready to check 3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the next include. 3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_type: One of the _XXX_HEADER constants defined above. 3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_is_header: Whether the file that owns this _IncludeState is itself a header 3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The empty string if the header is in the right order, or an 3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error message describing what's wrong. 3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _CONFIG_HEADER and file_is_header: 3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 'Header file should not contain WebCore config.h.' 3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _PRIMARY_HEADER and file_is_header: 3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 'Header file should not contain itself.' 334d0825bca7fe65beaee391d30da42e937db621564Steve Block if header_type == _MOC_HEADER: 335d0825bca7fe65beaee391d30da42e937db621564Steve Block return '' 3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = '' 3380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section != self._OTHER_SECTION: 3390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch before_error_message = ('Found %s before %s' % 3400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (self._TYPE_NAMES[header_type], 3410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._SECTION_NAMES[self._section + 1])) 3420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch after_error_message = ('Found %s after %s' % 3430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (self._TYPE_NAMES[header_type], 3440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._SECTION_NAMES[self._section])) 3450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _CONFIG_HEADER: 3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section >= self._CONFIG_SECTION: 3480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = after_error_message 3490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._CONFIG_SECTION 3500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif header_type == _PRIMARY_HEADER: 3510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section >= self._PRIMARY_SECTION: 3520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = after_error_message 3530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif self._section < self._CONFIG_SECTION: 3540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = before_error_message 3550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._PRIMARY_SECTION 3560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._visited_primary_section = True 3570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 3580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch assert header_type == _OTHER_HEADER 3590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not file_is_header and self._section < self._PRIMARY_SECTION: 3602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if primary_header_exists: 3612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch error_message = before_error_message 3620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._OTHER_SECTION 3630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return error_message 3650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 367cad810f21b803229eb11403f9209855525a25d57Steve Blockclass Position(object): 368cad810f21b803229eb11403f9209855525a25d57Steve Block """Holds the position of something.""" 369cad810f21b803229eb11403f9209855525a25d57Steve Block def __init__(self, row, column): 370cad810f21b803229eb11403f9209855525a25d57Steve Block self.row = row 371cad810f21b803229eb11403f9209855525a25d57Steve Block self.column = column 372cad810f21b803229eb11403f9209855525a25d57Steve Block 37365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch def __str__(self): 37465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return '(%s, %s)' % (self.row, self.column) 37565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 37665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch def __cmp__(self, other): 37765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return self.row.__cmp__(other.row) or self.column.__cmp__(other.column) 37865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 379cad810f21b803229eb11403f9209855525a25d57Steve Block 380cad810f21b803229eb11403f9209855525a25d57Steve Blockclass Parameter(object): 381cad810f21b803229eb11403f9209855525a25d57Steve Block """Information about one function parameter.""" 382cad810f21b803229eb11403f9209855525a25d57Steve Block def __init__(self, parameter, parameter_name_index, row): 383cad810f21b803229eb11403f9209855525a25d57Steve Block self.type = parameter[:parameter_name_index].strip() 384cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove any initializers from the parameter name (e.g. int i = 5). 385cad810f21b803229eb11403f9209855525a25d57Steve Block self.name = sub(r'=.*', '', parameter[parameter_name_index:]).strip() 386cad810f21b803229eb11403f9209855525a25d57Steve Block self.row = row 387cad810f21b803229eb11403f9209855525a25d57Steve Block 388cad810f21b803229eb11403f9209855525a25d57Steve Block @memoized 389cad810f21b803229eb11403f9209855525a25d57Steve Block def lower_with_underscores_name(self): 390cad810f21b803229eb11403f9209855525a25d57Steve Block """Returns the parameter name in the lower with underscores format.""" 391cad810f21b803229eb11403f9209855525a25d57Steve Block return _convert_to_lower_with_underscores(self.name) 392cad810f21b803229eb11403f9209855525a25d57Steve Block 393cad810f21b803229eb11403f9209855525a25d57Steve Block 394cad810f21b803229eb11403f9209855525a25d57Steve Blockclass SingleLineView(object): 395cad810f21b803229eb11403f9209855525a25d57Steve Block """Converts multiple lines into a single line (with line breaks replaced by a 396cad810f21b803229eb11403f9209855525a25d57Steve Block space) to allow for easier searching.""" 397cad810f21b803229eb11403f9209855525a25d57Steve Block def __init__(self, lines, start_position, end_position): 398cad810f21b803229eb11403f9209855525a25d57Steve Block """Create a SingleLineView instance. 399cad810f21b803229eb11403f9209855525a25d57Steve Block 400cad810f21b803229eb11403f9209855525a25d57Steve Block Args: 401cad810f21b803229eb11403f9209855525a25d57Steve Block lines: a list of multiple lines to combine into a single line. 402cad810f21b803229eb11403f9209855525a25d57Steve Block start_position: offset within lines of where to start the single line. 403cad810f21b803229eb11403f9209855525a25d57Steve Block end_position: just after where to end (like a slice operation). 404cad810f21b803229eb11403f9209855525a25d57Steve Block """ 405cad810f21b803229eb11403f9209855525a25d57Steve Block # Get the rows of interest. 406cad810f21b803229eb11403f9209855525a25d57Steve Block trimmed_lines = lines[start_position.row:end_position.row + 1] 407cad810f21b803229eb11403f9209855525a25d57Steve Block 408cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove the columns on the last line that aren't included. 409cad810f21b803229eb11403f9209855525a25d57Steve Block trimmed_lines[-1] = trimmed_lines[-1][:end_position.column] 410cad810f21b803229eb11403f9209855525a25d57Steve Block 411cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove the columns on the first line that aren't included. 412cad810f21b803229eb11403f9209855525a25d57Steve Block trimmed_lines[0] = trimmed_lines[0][start_position.column:] 413cad810f21b803229eb11403f9209855525a25d57Steve Block 414cad810f21b803229eb11403f9209855525a25d57Steve Block # Create a single line with all of the parameters. 415cad810f21b803229eb11403f9209855525a25d57Steve Block self.single_line = ' '.join(trimmed_lines) 416cad810f21b803229eb11403f9209855525a25d57Steve Block 417cad810f21b803229eb11403f9209855525a25d57Steve Block # Keep the row lengths, so we can calculate the original row number 418cad810f21b803229eb11403f9209855525a25d57Steve Block # given a column in the single line (adding 1 due to the space added 419cad810f21b803229eb11403f9209855525a25d57Steve Block # during the join). 420cad810f21b803229eb11403f9209855525a25d57Steve Block self._row_lengths = [len(line) + 1 for line in trimmed_lines] 421cad810f21b803229eb11403f9209855525a25d57Steve Block self._starting_row = start_position.row 422cad810f21b803229eb11403f9209855525a25d57Steve Block 423cad810f21b803229eb11403f9209855525a25d57Steve Block def convert_column_to_row(self, single_line_column_number): 424cad810f21b803229eb11403f9209855525a25d57Steve Block """Convert the column number from the single line into the original 425cad810f21b803229eb11403f9209855525a25d57Steve Block line number. 426cad810f21b803229eb11403f9209855525a25d57Steve Block 427cad810f21b803229eb11403f9209855525a25d57Steve Block Special cases: 428cad810f21b803229eb11403f9209855525a25d57Steve Block * Columns in the added spaces are considered part of the previous line. 429cad810f21b803229eb11403f9209855525a25d57Steve Block * Columns beyond the end of the line are consider part the last line 430cad810f21b803229eb11403f9209855525a25d57Steve Block in the view.""" 431cad810f21b803229eb11403f9209855525a25d57Steve Block total_columns = 0 432cad810f21b803229eb11403f9209855525a25d57Steve Block row_offset = 0 433cad810f21b803229eb11403f9209855525a25d57Steve Block while row_offset < len(self._row_lengths) - 1 and single_line_column_number >= total_columns + self._row_lengths[row_offset]: 434cad810f21b803229eb11403f9209855525a25d57Steve Block total_columns += self._row_lengths[row_offset] 435cad810f21b803229eb11403f9209855525a25d57Steve Block row_offset += 1 436cad810f21b803229eb11403f9209855525a25d57Steve Block return self._starting_row + row_offset 437cad810f21b803229eb11403f9209855525a25d57Steve Block 438cad810f21b803229eb11403f9209855525a25d57Steve Block 439cad810f21b803229eb11403f9209855525a25d57Steve Blockdef create_skeleton_parameters(all_parameters): 440cad810f21b803229eb11403f9209855525a25d57Steve Block """Converts a parameter list to a skeleton version. 441cad810f21b803229eb11403f9209855525a25d57Steve Block 442cad810f21b803229eb11403f9209855525a25d57Steve Block The skeleton only has one word for the parameter name, one word for the type, 443cad810f21b803229eb11403f9209855525a25d57Steve Block and commas after each parameter and only there. Everything in the skeleton 444cad810f21b803229eb11403f9209855525a25d57Steve Block remains in the same columns as the original.""" 445cad810f21b803229eb11403f9209855525a25d57Steve Block all_simplifications = ( 446cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove template parameters, function declaration parameters, etc. 447cad810f21b803229eb11403f9209855525a25d57Steve Block r'(<[^<>]*?>)|(\([^\(\)]*?\))|(\{[^\{\}]*?\})', 448cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove all initializers. 449cad810f21b803229eb11403f9209855525a25d57Steve Block r'=[^,]*', 450cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove :: and everything before it. 451cad810f21b803229eb11403f9209855525a25d57Steve Block r'[^,]*::', 452cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove modifiers like &, *. 453cad810f21b803229eb11403f9209855525a25d57Steve Block r'[&*]', 454cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove const modifiers. 455cad810f21b803229eb11403f9209855525a25d57Steve Block r'\bconst\s+(?=[A-Za-z])', 456cad810f21b803229eb11403f9209855525a25d57Steve Block # Remove numerical modifiers like long. 457cad810f21b803229eb11403f9209855525a25d57Steve Block r'\b(unsigned|long|short)\s+(?=unsigned|long|short|int|char|double|float)') 458cad810f21b803229eb11403f9209855525a25d57Steve Block 459cad810f21b803229eb11403f9209855525a25d57Steve Block skeleton_parameters = all_parameters 460cad810f21b803229eb11403f9209855525a25d57Steve Block for simplification in all_simplifications: 461cad810f21b803229eb11403f9209855525a25d57Steve Block skeleton_parameters = iteratively_replace_matches_with_char(simplification, ' ', skeleton_parameters) 462cad810f21b803229eb11403f9209855525a25d57Steve Block # If there are any parameters, then add a , after the last one to 463cad810f21b803229eb11403f9209855525a25d57Steve Block # make a regular pattern of a , following every parameter. 464cad810f21b803229eb11403f9209855525a25d57Steve Block if skeleton_parameters.strip(): 465cad810f21b803229eb11403f9209855525a25d57Steve Block skeleton_parameters += ',' 466cad810f21b803229eb11403f9209855525a25d57Steve Block return skeleton_parameters 467cad810f21b803229eb11403f9209855525a25d57Steve Block 468cad810f21b803229eb11403f9209855525a25d57Steve Block 469cad810f21b803229eb11403f9209855525a25d57Steve Blockdef find_parameter_name_index(skeleton_parameter): 470cad810f21b803229eb11403f9209855525a25d57Steve Block """Determines where the parametere name starts given the skeleton parameter.""" 471cad810f21b803229eb11403f9209855525a25d57Steve Block # The first space from the right in the simplified parameter is where the parameter 472cad810f21b803229eb11403f9209855525a25d57Steve Block # name starts unless the first space is before any content in the simplified parameter. 473cad810f21b803229eb11403f9209855525a25d57Steve Block before_name_index = skeleton_parameter.rstrip().rfind(' ') 474cad810f21b803229eb11403f9209855525a25d57Steve Block if before_name_index != -1 and skeleton_parameter[:before_name_index].strip(): 475cad810f21b803229eb11403f9209855525a25d57Steve Block return before_name_index + 1 476cad810f21b803229eb11403f9209855525a25d57Steve Block return len(skeleton_parameter) 477cad810f21b803229eb11403f9209855525a25d57Steve Block 478cad810f21b803229eb11403f9209855525a25d57Steve Block 479cad810f21b803229eb11403f9209855525a25d57Steve Blockdef parameter_list(elided_lines, start_position, end_position): 480cad810f21b803229eb11403f9209855525a25d57Steve Block """Generator for a function's parameters.""" 481cad810f21b803229eb11403f9209855525a25d57Steve Block # Create new positions that omit the outer parenthesis of the parameters. 482cad810f21b803229eb11403f9209855525a25d57Steve Block start_position = Position(row=start_position.row, column=start_position.column + 1) 483cad810f21b803229eb11403f9209855525a25d57Steve Block end_position = Position(row=end_position.row, column=end_position.column - 1) 484cad810f21b803229eb11403f9209855525a25d57Steve Block single_line_view = SingleLineView(elided_lines, start_position, end_position) 485cad810f21b803229eb11403f9209855525a25d57Steve Block skeleton_parameters = create_skeleton_parameters(single_line_view.single_line) 486cad810f21b803229eb11403f9209855525a25d57Steve Block end_index = -1 487cad810f21b803229eb11403f9209855525a25d57Steve Block 488cad810f21b803229eb11403f9209855525a25d57Steve Block while True: 489cad810f21b803229eb11403f9209855525a25d57Steve Block # Find the end of the next parameter. 490cad810f21b803229eb11403f9209855525a25d57Steve Block start_index = end_index + 1 491cad810f21b803229eb11403f9209855525a25d57Steve Block end_index = skeleton_parameters.find(',', start_index) 492cad810f21b803229eb11403f9209855525a25d57Steve Block 493cad810f21b803229eb11403f9209855525a25d57Steve Block # No comma means that all parameters have been parsed. 494cad810f21b803229eb11403f9209855525a25d57Steve Block if end_index == -1: 495cad810f21b803229eb11403f9209855525a25d57Steve Block return 496cad810f21b803229eb11403f9209855525a25d57Steve Block row = single_line_view.convert_column_to_row(end_index) 497cad810f21b803229eb11403f9209855525a25d57Steve Block 498cad810f21b803229eb11403f9209855525a25d57Steve Block # Parse the parameter into a type and parameter name. 499cad810f21b803229eb11403f9209855525a25d57Steve Block skeleton_parameter = skeleton_parameters[start_index:end_index] 500cad810f21b803229eb11403f9209855525a25d57Steve Block name_offset = find_parameter_name_index(skeleton_parameter) 501cad810f21b803229eb11403f9209855525a25d57Steve Block parameter = single_line_view.single_line[start_index:end_index] 502cad810f21b803229eb11403f9209855525a25d57Steve Block yield Parameter(parameter, name_offset, row) 503cad810f21b803229eb11403f9209855525a25d57Steve Block 504cad810f21b803229eb11403f9209855525a25d57Steve Block 505d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass _FunctionState(object): 506d0825bca7fe65beaee391d30da42e937db621564Steve Block """Tracks current function name and the number of lines in its body. 5070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 508d0825bca7fe65beaee391d30da42e937db621564Steve Block Attributes: 509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block min_confidence: The minimum confidence level to use while checking style. 5100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 5140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 5150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 516dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def __init__(self, min_confidence): 517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block self.min_confidence = min_confidence 518dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block self.current_function = '' 5190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = False 5200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines_in_function = 0 52165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # Make sure these will not be mistaken for real positions (even when a 5226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # small amount is added to them). 52365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.body_start_position = Position(-1000, 0) 52465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.end_position = Position(-1000, 0) 5250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 52665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch def begin(self, function_name, function_name_start_position, body_start_position, end_position, 527cad810f21b803229eb11403f9209855525a25d57Steve Block parameter_start_position, parameter_end_position, clean_lines): 5280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Start analyzing function body. 5290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 5310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_name: The name of the function being tracked. 53265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch function_name_start_position: Position in elided where the function name starts. 53365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch body_start_position: Position in elided of the { or the ; for a prototype. 53465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch end_position: Position in elided just after the final } (or ; is. 53565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch parameter_start_position: Position in elided of the '(' for the parameters. 53665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch parameter_end_position: Position in elided just after the ')' for the parameters. 537cad810f21b803229eb11403f9209855525a25d57Steve Block clean_lines: A CleansedLines instance containing the file. 5380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = True 540f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self.lines_in_function = -1 # Don't count the open brace line. 5410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.current_function = function_name 54265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.function_name_start_position = function_name_start_position 54365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.body_start_position = body_start_position 54465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.end_position = end_position 54565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.is_declaration = clean_lines.elided[body_start_position.row][body_start_position.column] == ';' 546cad810f21b803229eb11403f9209855525a25d57Steve Block self.parameter_start_position = parameter_start_position 547cad810f21b803229eb11403f9209855525a25d57Steve Block self.parameter_end_position = parameter_end_position 54865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.is_pure = False 54965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if self.is_declaration: 55065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch characters_after_parameters = SingleLineView(clean_lines.elided, parameter_end_position, body_start_position).single_line 55165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch self.is_pure = bool(match(r'\s*=\s*0\s*', characters_after_parameters)) 552cad810f21b803229eb11403f9209855525a25d57Steve Block self._clean_lines = clean_lines 553cad810f21b803229eb11403f9209855525a25d57Steve Block self._parameter_list = None 554cad810f21b803229eb11403f9209855525a25d57Steve Block 5552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def modifiers_and_return_type(self): 5562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Returns the modifiers and the return type.""" 5572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # Go backwards from where the function name is until we encounter one of several things: 5582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # ';' or '{' or '}' or 'private:', etc. or '#' or return Position(0, 0) 5592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block elided = self._clean_lines.elided 5602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block start_modifiers = _rfind_in_lines(r';|\{|\}|((private|public|protected):)|(#.*)', 5612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block elided, self.parameter_start_position, Position(0, 0)) 5622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return SingleLineView(elided, start_modifiers, self.function_name_start_position).single_line.strip() 5632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 564cad810f21b803229eb11403f9209855525a25d57Steve Block def parameter_list(self): 565cad810f21b803229eb11403f9209855525a25d57Steve Block if not self._parameter_list: 566cad810f21b803229eb11403f9209855525a25d57Steve Block # Store the final result as a tuple since that is immutable. 567cad810f21b803229eb11403f9209855525a25d57Steve Block self._parameter_list = tuple(parameter_list(self._clean_lines.elided, self.parameter_start_position, self.parameter_end_position)) 568cad810f21b803229eb11403f9209855525a25d57Steve Block 569cad810f21b803229eb11403f9209855525a25d57Steve Block return self._parameter_list 5700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner def count(self, line_number): 5720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Count line in current function body.""" 57365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if self.in_a_function and line_number >= self.body_start_position.row: 5740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines_in_function += 1 5750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 576d0825bca7fe65beaee391d30da42e937db621564Steve Block def check(self, error, line_number): 5770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Report if too many lines in function body. 5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 5800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 5810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 5820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'T(EST|est)', self.current_function): 5840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_trigger = self._TEST_TRIGGER 5850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 5860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_trigger = self._NORMAL_TRIGGER 587dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block trigger = base_trigger * 2 ** self.min_confidence 5880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self.lines_in_function > trigger: 5900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_level = int(math.log(self.lines_in_function / base_trigger, 2)) 5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... 5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if error_level > 5: 5930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_level = 5 594d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/fn_size', error_level, 5950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Small and focused functions are preferred:' 5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' %s has %d non-comment lines' 5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' (error triggered by exceeding %d lines).' % ( 5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.current_function, self.lines_in_function, trigger)) 5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def end(self): 6016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Stop analyzing function body.""" 6020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = False 6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _IncludeError(Exception): 6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Indicates a problem with the include order in a file.""" 6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pass 6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass FileInfo: 6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Provides utility functions for filenames. 6120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch FileInfo provides easy access to the components of a file's path 6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch relative to the project root. 6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, filename): 6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._filename = filename 6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def full_name(self): 6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Make Windows paths like Unix.""" 6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return os.path.abspath(self._filename).replace('\\', '/') 6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def repository_name(self): 6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Full name after removing the local path to the repository. 6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch If we have a real absolute path name here we can try to do something smart: 6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch detecting the root of the checkout and truncating /path/to/checkout from 6290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the name so that we get header guards that don't include things like 6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "C:\Documents and Settings\..." or "/home/username/..." in them and thus 6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch people on different computers who have checked the source out to different 6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch locations won't see bogus errors. 6330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 6340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch fullname = self.full_name() 6350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(fullname): 6370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch project_dir = os.path.dirname(fullname) 6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(os.path.join(project_dir, ".svn")): 6400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If there's a .svn file in the current directory, we 6410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # recursively look up the directory tree for the top 6420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # of the SVN checkout 6430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = project_dir 6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch one_up_dir = os.path.dirname(root_dir) 6450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while os.path.exists(os.path.join(one_up_dir, ".svn")): 6460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(root_dir) 6470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch one_up_dir = os.path.dirname(one_up_dir) 6480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch prefix = os.path.commonprefix([root_dir, project_dir]) 6500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname[len(prefix) + 1:] 6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Not SVN? Try to find a git top level directory by 6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # searching up from the current path. 6540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(fullname) 6550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (root_dir != os.path.dirname(root_dir) 6560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not os.path.exists(os.path.join(root_dir, ".git"))): 6570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(root_dir) 6580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(os.path.join(root_dir, ".git")): 6590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch prefix = os.path.commonprefix([root_dir, project_dir]) 6600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname[len(prefix) + 1:] 6610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't know what to do; header guard warnings may be wrong... 6630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname 6640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def split(self): 6660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Splits the file into the directory, basename, and extension. 6670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For 'chrome/browser/browser.cpp', Split() would 6690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ('chrome/browser', 'browser', '.cpp') 6700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 6720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch A tuple of (directory, basename, extension). 6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 6740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch googlename = self.repository_name() 6760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch project, rest = os.path.split(googlename) 6770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (project,) + os.path.splitext(rest) 6780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def base_name(self): 6800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File base name - text after the final slash, before the final period.""" 6810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.split()[1] 6820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def extension(self): 6840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File extension - text following the final period.""" 6850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.split()[2] 6860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def no_extension(self): 6880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File has no source file extension.""" 6890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '/'.join(self.split()[0:2]) 6900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def is_source(self): 6920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File has a source file extension.""" 6930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.extension()[1:] in ('c', 'cc', 'cpp', 'cxx') 6940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. 6970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( 6980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') 6990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches strings. Escape codes should already be removed by ESCAPES. 7000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') 7010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches characters. Escape codes should already be removed by ESCAPES. 7020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") 7030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches multi-line C++ comments. 7040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# This RE is a little bit more complicated than one might expect, because we 7050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# have to take care of space removals tools so we can handle comments inside 7060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# statements better. 7070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# The current rule is: We only clear spaces from both sides when we're at the 7080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# end of the line. Otherwise, we try to remove spaces from the right side, 7090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# if this doesn't work we try on left side but only if there's a non-character 7100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# on the right. 7110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( 7120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r"""(\s*/\*.*\*/\s*$| 7130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /\*.*\*/\s+| 7140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch \s+/\*.*\*/(?=\W)| 7150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /\*.*\*/)""", re.VERBOSE) 7160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef is_cpp_string(line): 7190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Does line terminate so, that the next symbol is in string constant. 7200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function does not consider single-line nor multi-line comments. 7220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 7240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: is a partial line of code starting from the 0..n. 7250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 7270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True, if next character appended to 'line' is inside a 7280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch string constant. 7290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" 7320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 7330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef find_next_multi_line_comment_start(lines, line_index): 7360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Find the beginning marker for a multiline comment.""" 7370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 7380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().startswith('/*'): 7390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only return this marker if the comment goes beyond this line 7400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().find('*/', 2) < 0: 7410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return line_index 7420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index += 1 7430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(lines) 7440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef find_next_multi_line_comment_end(lines, line_index): 7470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """We are inside a comment, find the end marker.""" 7480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 7490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().endswith('*/'): 7500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return line_index 7510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index += 1 7520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(lines) 7530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef remove_multi_line_comments_from_range(lines, begin, end): 7560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Clears a range of lines for multi-line comments.""" 7570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Having // dummy comments makes the lines non-empty, so we will not get 7580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # unnecessary blank line warnings later in the code. 7590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for i in range(begin, end): 7600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines[i] = '// dummy' 7610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 763d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef remove_multi_line_comments(lines, error): 7640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Removes multiline (c-style) comments from lines.""" 7650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index = 0 7660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 7670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index_begin = find_next_multi_line_comment_start(lines, line_index) 7680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_index_begin >= len(lines): 7690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 7700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index_end = find_next_multi_line_comment_end(lines, line_index_begin) 7710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_index_end >= len(lines): 772d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_index_begin + 1, 'readability/multiline_comment', 5, 7730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Could not find end of multi-line comment') 7740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 7750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remove_multi_line_comments_from_range(lines, line_index_begin, line_index_end + 1) 7760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index = line_index_end + 1 7770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef cleanse_comments(line): 7800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Removes //-comments and single-line C-style /* */ comments. 7810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 7830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A line of C++ source. 7840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 7860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The line with single-line comments removed. 7870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch comment_position = line.find('//') 7890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if comment_position != -1 and not is_cpp_string(line[:comment_position]): 7900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line[:comment_position] 7910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # get rid of /* ... */ 7920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) 7930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass CleansedLines(object): 7960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Holds 3 copies of all lines with different preprocessing applied to them. 7970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1) elided member contains lines without strings and comments, 7990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2) lines member contains lines without comments, and 8000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3) raw member contains all the lines without processing. 8010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch All these three members are of <type 'list'>, and of the same length. 8020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 8030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, lines): 8050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.elided = [] 8060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines = [] 8070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.raw_lines = lines 8080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._num_lines = len(lines) 8090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number in range(len(lines)): 8100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines.append(cleanse_comments(lines[line_number])) 8110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = self.collapse_strings(lines[line_number]) 8120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.elided.append(cleanse_comments(elided)) 8130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def num_lines(self): 8150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns the number of lines represented.""" 8160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self._num_lines 8170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch @staticmethod 8190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def collapse_strings(elided): 8200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Collapses strings and chars on a line to simple "" or '' blocks. 8210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch We nix strings first so we're not fooled by text like '"http://"' 8230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 8250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided: The line being processed. 8260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 8280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The line with collapsed strings. 8290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 8300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not _RE_PATTERN_INCLUDE.match(elided): 8310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove escaped characters first to make quote/single quote collapsing 8320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # basic. Things that look like escaped characters shouldn't occur 8330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # outside of strings and chars. 8340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) 8350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) 8360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) 8370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return elided 8380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 84065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochdef close_expression(elided, position): 8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """If input points to ( or { or [, finds the position that closes it. 8420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 84365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch If elided[position.row][position.column] points to a '(' or '{' or '[', 84465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch finds the line_number/pos that correspond to the closing of the expression. 8450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 84665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Args: 84765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch elided: A CleansedLines.elided instance containing the file. 84865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch position: The position of the opening item. 8490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 85065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Returns: 85165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch The Position *past* the closing brace, or Position(len(elided), -1) 85265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if we never find a close. Note we ignore strings and comments when matching. 8530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 85465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch line = elided[position.row] 85565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch start_character = line[position.column] 8560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if start_character == '(': 85765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch enclosing_character_regex = r'[\(\)]' 85865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch elif start_character == '[': 85965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch enclosing_character_regex = r'[\[\]]' 86065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch elif start_character == '{': 86165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch enclosing_character_regex = r'[\{\}]' 86265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch else: 86365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return Position(len(elided), -1) 86465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 86565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch current_column = position.column + 1 86665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch line_number = position.row 86765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch net_open = 1 86865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch for line in elided[position.row:]: 86965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch line = line[current_column:] 87065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 87165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # Search the current line for opening and closing characters. 87265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch while True: 87365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch next_enclosing_character = search(enclosing_character_regex, line) 87465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # No more on this line. 87565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if not next_enclosing_character: 87665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch break 87765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch current_column += next_enclosing_character.end(0) 87865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch line = line[next_enclosing_character.end(0):] 87965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if next_enclosing_character.group(0) == start_character: 88065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch net_open += 1 88165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch else: 88265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch net_open -= 1 88365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if not net_open: 88465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return Position(line_number, current_column) 88565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 88665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # Proceed to the next line. 8870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number += 1 88865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch current_column = 0 8890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 89065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # The given item was not closed. 89165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return Position(len(elided), -1) 8920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 893d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_copyright(lines, error): 8940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if no Copyright message appears at the top of the file.""" 8950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We'll say it should occur by line 10. Don't forget there's a 8970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # dummy line at the front. 8980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in xrange(1, min(len(lines), 11)): 8990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if re.search(r'Copyright', lines[line], re.I): 9000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 9010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: # means no copyright line was found 902d0825bca7fe65beaee391d30da42e937db621564Steve Block error(0, 'legal/copyright', 5, 9030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'No copyright message found. ' 9040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You should have a line: "Copyright [year] <Copyright Owner>"') 9050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_header_guard_cpp_variable(filename): 9080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns the CPP variable that should be used as a header guard. 9090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 9110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of a C++ header file. 9120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 9140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The CPP variable that should be used as a header guard in the 9150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch named file. 9160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 9180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 919dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block # Restores original filename in case that style checker is invoked from Emacs's 920dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block # flymake. 921dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block filename = re.sub(r'_flymake\.h$', '.h', filename) 922dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 923f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch standard_name = sub(r'[-.\s]', '_', os.path.basename(filename)) 924f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 925f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Files under WTF typically have header guards that start with WTF_. 926f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if filename.find('/wtf/'): 927f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch special_name = "WTF_" + standard_name 928f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else: 929f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch special_name = standard_name 930f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return (special_name, standard_name) 9310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef check_for_header_guard(filename, lines, error): 9340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks that the file contains a header guard. 9350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Logs an error if no #ifndef header guard is present. For other 9370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch headers, checks that the full pathname is used. 9380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 9400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the C++ header file. 9410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 9420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 9430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 9440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cppvar = get_header_guard_cpp_variable(filename) 9460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef = None 9480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef_line_number = 0 9490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch define = None 9500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number, line in enumerate(lines): 9510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_split = line.split() 9520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if len(line_split) >= 2: 9530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # find the first occurrence of #ifndef and #define, save arg 9540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not ifndef and line_split[0] == '#ifndef': 9550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # set ifndef to the header guard presented on the #ifndef line. 9560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef = line_split[1] 9570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef_line_number = line_number 9580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not define and line_split[0] == '#define': 9590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch define = line_split[1] 960d0825bca7fe65beaee391d30da42e937db621564Steve Block if define and ifndef: 961d0825bca7fe65beaee391d30da42e937db621564Steve Block break 9620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not ifndef or not define or ifndef != define: 964d0825bca7fe65beaee391d30da42e937db621564Steve Block error(0, 'build/header_guard', 5, 9650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'No #ifndef header guard found, suggested CPP variable is: %s' % 966f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch cppvar[0]) 9670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 9680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 969d0825bca7fe65beaee391d30da42e937db621564Steve Block # The guard should be File_h. 970f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if ifndef not in cppvar: 971d0825bca7fe65beaee391d30da42e937db621564Steve Block error(ifndef_line_number, 'build/header_guard', 5, 972f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch '#ifndef header guard has wrong style, please use: %s' % cppvar[0]) 9730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 975d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_unicode_replacement_characters(lines, error): 9760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error for each line containing Unicode replacement characters. 9770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch These indicate that either the file contained invalid UTF-8 (likely) 9790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or Unicode replacement characters (which it shouldn't). Note that 9800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch it's possible for this to throw off line numbering if the invalid 9810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch UTF-8 occurred adjacent to a newline. 9820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 9840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 9850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 9860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 9870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number, line in enumerate(lines): 9880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if u'\ufffd' in line: 989d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/utf8', 5, 9900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line contains invalid UTF-8 (or Unicode replacement character).') 9910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 993d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_new_line_at_eof(lines, error): 9940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if there is no newline char at the end of the file. 9950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 9970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 9980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 9990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 10000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The array lines() was created by adding two newlines to the 10020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # original file (go figure), then splitting on \n. 10030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # To verify that the file ends in \n, we just have to make sure the 10040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # last-but-two element of lines() exists and is empty. 10050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if len(lines) < 3 or lines[-2]: 1006d0825bca7fe65beaee391d30da42e937db621564Steve Block error(len(lines) - 2, 'whitespace/ending_newline', 5, 10070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Could not find a newline character at the end of the file.') 10080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1010d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_multiline_comments_and_strings(clean_lines, line_number, error): 10110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if we see /* ... */ or "..." that extend past one line. 10120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /* ... */ comments are legit inside macros, for one line. 10140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Otherwise, we prefer // comments, so it's ok to warn about the 10150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch other. Likewise, it's ok for strings to extend across multiple 10160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines, as long as a line continuation character (backslash) 10170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch terminates each line. Although not currently prohibited by the C++ 10180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch style guide, it's ugly and unnecessary. We don't do well with either 10190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch in this lint program, so we warn about both. 10200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 10220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 10230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 10240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 10250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 10260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 10270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove all \\ (escaped backslashes) from the line. They are OK, and the 10290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # second (escaped) slash may trigger later \" detection erroneously. 10300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace('\\\\', '') 10310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.count('/*') > line.count('*/'): 1033d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/multiline_comment', 5, 10340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Complex multi-line /*...*/-style comment found. ' 10350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Lint may give bogus warnings. ' 10360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider replacing these with //-style comments, ' 10370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'with #if 0...#endif, ' 10380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'or with more clearly structured multi-line comments.') 10390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (line.count('"') - line.count('\\"')) % 2: 1041d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/multiline_string', 5, 10420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Multi-line string ("...") found. This lint script doesn\'t ' 10430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'do well with such strings, and may give bogus warnings. They\'re ' 10440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ugly and unnecessary, and you should use concatenation instead".') 10450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_THREADING_LIST = ( 10480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('asctime(', 'asctime_r('), 10490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('ctime(', 'ctime_r('), 10500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getgrgid(', 'getgrgid_r('), 10510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getgrnam(', 'getgrnam_r('), 10520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getlogin(', 'getlogin_r('), 10530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getpwnam(', 'getpwnam_r('), 10540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getpwuid(', 'getpwuid_r('), 10550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('gmtime(', 'gmtime_r('), 10560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('localtime(', 'localtime_r('), 10570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('rand(', 'rand_r('), 10580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('readdir(', 'readdir_r('), 10590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('strtok(', 'strtok_r('), 10600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('ttyname(', 'ttyname_r('), 10610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ) 10620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1064d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_posix_threading(clean_lines, line_number, error): 10650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for calls to thread-unsafe functions. 10660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Much code has been originally written without consideration of 10680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch multi-threading. Also, engineers are relying on their old experience; 10690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch they have learned posix before threading extensions were added. These 10700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tests guide the engineers to use thread-safe functions (when using 10710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch posix directly). 10720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 10740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 10750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 10760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 10770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 10780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 10790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for single_thread_function, multithread_safe_function in _THREADING_LIST: 10800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch index = line.find(single_thread_function) 10810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 10820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if index >= 0 and (index == 0 or (not line[index - 1].isalnum() 10830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line[index - 1] not in ('_', '.', '>'))): 1084d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/threadsafe_fn', 2, 10850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider using ' + multithread_safe_function + 10860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '...) instead of ' + single_thread_function + 10870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '...) for improved thread safety.') 10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches invalid increment: *count++, which moves pointer instead of 10910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# incrementing a value. 10920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INVALID_INCREMENT = re.compile( 10930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'^\s*\*\w+(\+\+|--);') 10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1096d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_invalid_increment(clean_lines, line_number, error): 10970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for invalid increment *count++. 10980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example following function: 11000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch void increment_counter(int* count) { 11010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *count++; 11020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 11030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is invalid, because it effectively does count++, moving pointer, and should 11040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch be replaced with ++*count, (*count)++ or *count += 1. 11050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 11070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 11080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 11090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 11100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 11120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if _RE_PATTERN_INVALID_INCREMENT.match(line): 1113d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/invalid_increment', 5, 11140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Changing pointer instead of value (or unused value of operator*).') 11150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _ClassInfo(object): 11180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Stores information about a class.""" 11190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, name, line_number): 11210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.name = name 11220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.line_number = line_number 11230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.seen_open_brace = False 11240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.is_derived = False 11250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.virtual_method_line_number = None 11260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.has_virtual_destructor = False 11270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.brace_depth = 0 11280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _ClassState(object): 11310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Holds the current state of the parse relating to class declarations. 11320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch It maintains a stack of _ClassInfos representing the parser's guess 11340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch as to the current nesting of class declarations. The innermost class 11350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is at the top (back) of the stack. Typically, the stack will either 11360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch be empty or have exactly one entry. 11370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self): 11400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.classinfo_stack = [] 11410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1142d0825bca7fe65beaee391d30da42e937db621564Steve Block def check_finished(self, error): 11430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks that all classes have been completely parsed. 11440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Call this when all lines in a file have been processed. 11460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 11470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 11480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self.classinfo_stack: 11500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note: This test can result in false positives if #ifdef constructs 11510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # get in the way of brace matching. See the testBuildClass test in 11520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # cpp_style_unittest.py for an example of this. 1153d0825bca7fe65beaee391d30da42e937db621564Steve Block error(self.classinfo_stack[0].line_number, 'build/class', 5, 11540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Failed to find complete declaration of class %s' % 11550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.classinfo_stack[0].name) 11560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1158643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass _FileState(object): 1159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def __init__(self, clean_lines, file_extension): 1160643ca7872b450ea4efacab6188849e5aac2ba161Steve Block self._did_inside_namespace_indent_warning = False 1161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._clean_lines = clean_lines 1162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if file_extension in ['m', 'mm']: 1163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_objective_c = True 1164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elif file_extension == 'h': 1165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # In the case of header files, it is unknown if the file 1166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # is objective c or not, so set this value to None and then 1167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # if it is requested, use heuristics to guess the value. 1168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_objective_c = None 1169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else: 1170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_objective_c = False 1171f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_c = file_extension == 'c' 1172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block def set_did_inside_namespace_indent_warning(self): 1174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block self._did_inside_namespace_indent_warning = True 1175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block def did_inside_namespace_indent_warning(self): 1177643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return self._did_inside_namespace_indent_warning 1178643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def is_objective_c(self): 1180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if self._is_objective_c is None: 1181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for line in self._clean_lines.elided: 1182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Starting with @ or #import seem like the best indications 1183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # that we have an Objective C file. 1184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if line.startswith("@") or line.startswith("#import"): 1185f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_objective_c = True 1186f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch break 1187f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else: 1188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch self._is_objective_c = False 1189f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return self._is_objective_c 1190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def is_c_or_objective_c(self): 1192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch """Return whether the file extension corresponds to C or Objective-C.""" 1193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return self._is_c or self.is_objective_c() 1194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1196d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_non_standard_constructs(clean_lines, line_number, 11970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state, error): 11980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 11990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Complain about several constructs which gcc-2 accepts, but which are 12010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch not standard C++. Warning about these in lint is one way to ease the 12020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch transition to new compilers. 12030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - put storage class first (e.g. "static const" instead of "const static"). 12040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "%lld" instead of %qd" in printf-type functions. 12050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "%1$d" is non-standard in printf-type functions. 12060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "\%" is an undefined character escape sequence. 12070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - text after #endif is not allowed. 12080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - invalid inner-style forward declaration. 12090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - >? and <? operators, and their >?= and <?= cousins. 12100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - classes with virtual methods need virtual destructors (compiler warning 12110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch available, but not turned on yet.) 12120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Additionally, check for constructor/destructor style violations as it 12140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is very convenient to do so while checking for gcc-2 compliance. 12150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 12170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 12180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 12190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state: A _ClassState instance which maintains information about 12200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the current stack of nested class declarations being parsed. 1221d0825bca7fe65beaee391d30da42e937db621564Steve Block error: A callable to which errors are reported, which takes parameters: 1222d0825bca7fe65beaee391d30da42e937db621564Steve Block line number, error level, and message 12230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 12240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove comments from the line, but leave in strings for now. 12260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.lines[line_number] 12270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): 1229d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf_format', 3, 12300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%q in format strings is deprecated. Use %ll instead.') 12310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'printf\s*\(.*".*%\d+\$', line): 1233d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf_format', 2, 12340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%N$ formats are unconventional. Try rewriting to avoid them.') 12350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove escaped backslashes before looking for undefined escapes. 12370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace('\\\\', '') 12380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'("|\').*\\(%|\[|\(|{)', line): 1240d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/printf_format', 3, 12410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%, [, (, and { are undefined character escapes. Unescape them.') 12420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For the rest, work with both comments and strings removed. 12440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 12450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\b(const|volatile|void|char|short|int|long' 12470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'|float|double|signed|unsigned' 12480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'|schar|u?int8|u?int16|u?int32|u?int64)' 12490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s+(auto|register|static|extern|typedef)\b', 12500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line): 1251d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/storage_class', 5, 12520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Storage class (static, extern, typedef, etc) should be first.') 12530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*#\s*endif\s*[^/\s]+', line): 1255d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/endif_comment', 5, 12560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Uncommented text after #endif is non-standard. Use a comment.') 12570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): 1259d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/forward_decl', 5, 12600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Inner-style forward declarations are invalid. Remove this line.') 12610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', line): 1263d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/deprecated', 3, 12640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '>? and <? (max and min) operators are non-standard and deprecated.') 12650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Track class entry and exit, and attempt to find cases within the 12670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # class declaration that don't meet the C++ style 12680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # guidelines. Tracking is very dependent on the code matching Google 12690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # style guidelines, but it seems to perform well enough in testing 12700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # to be a worthwhile addition to the checks. 12710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack = class_state.classinfo_stack 12720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for a class declaration 12730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_decl_match = match( 12740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line) 12750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if class_decl_match: 12760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack.append(_ClassInfo(class_decl_match.group(3), line_number)) 12770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Everything else in this function uses the top of the stack if it's 12790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # not empty. 12800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo_stack: 12810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 12820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo = classinfo_stack[-1] 12840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the opening brace hasn't been seen look for it and also 12860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # parent class declarations. 12870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo.seen_open_brace: 12880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the line has a ';' in it, assume it's a forward declaration or 12890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a single-line class declaration, which we won't process. 12900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.find(';') != -1: 12910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack.pop() 12920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 12930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.seen_open_brace = (line.find('{') != -1) 12940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for a bare ':' 12950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search('(^|[^:]):($|[^:])', line): 12960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.is_derived = True 12970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo.seen_open_brace: 12980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return # Everything else in this function is for after open brace 12990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The class may have been declared with namespace or classname qualifiers. 13010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The constructor and destructor will not have those qualifiers. 13020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_classname = classinfo.name.split('::')[-1] 13030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for single-argument constructors that aren't marked explicit. 13050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Technically a valid construct, but against style. 13060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch args = match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)' 13070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % re.escape(base_classname), 13080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line) 13090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (args 13100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and args.group(1) != 'void' 13110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not match(r'(const\s+)?%s\s*&' % re.escape(base_classname), 13120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch args.group(1).strip())): 1313d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/explicit', 5, 13140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Single-argument constructors should be marked explicit.') 13150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for methods declared virtual. 13170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bvirtual\b', line): 13180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.virtual_method_line_number = line_number 13190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only look for a destructor declaration on the same line. It would 13200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # be extremely unlikely for the destructor declaration to occupy 13210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # more than one line. 13220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'~%s\s*\(' % base_classname, line): 13230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.has_virtual_destructor = True 13240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for class end. 13260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch brace_depth = classinfo.brace_depth 13270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch brace_depth = brace_depth + line.count('{') - line.count('}') 13280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if brace_depth <= 0: 13290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo = classinfo_stack.pop() 13300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Try to detect missing virtual destructor declarations. 13310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For now, only warn if a non-derived class with virtual methods lacks 13320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a virtual destructor. This is to make it less likely that people will 13330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # declare derived virtual destructors without declaring the base 13340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # destructor virtual. 13350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ((classinfo.virtual_method_line_number is not None) 13360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (not classinfo.has_virtual_destructor) 13370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (not classinfo.is_derived)): # Only warn for base classes 1338d0825bca7fe65beaee391d30da42e937db621564Steve Block error(classinfo.line_number, 'runtime/virtual', 4, 13390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'The class %s probably needs a virtual destructor due to ' 13400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'having virtual method(s), one declared at line %d.' 13410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (classinfo.name, classinfo.virtual_method_line_number)) 13420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 13430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.brace_depth = brace_depth 13440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1346d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_spacing_for_function_call(line, line_number, error): 13470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for the correctness of various spacing around function calls. 13480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 13500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The text of the line to check. 13510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 13520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 13530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 13540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Since function calls often occur inside if/for/foreach/while/switch 13560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # expressions - which have their own, more liberal conventions - we 13570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # first see if we should be looking inside such an expression for a 13580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function call, to which we can apply more strict standards. 13590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_call = line # if there's no control flow construct, look at whole line 13600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern in (r'\bif\s*\((.*)\)\s*{', 13610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bfor\s*\((.*)\)\s*{', 13620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bforeach\s*\((.*)\)\s*{', 13630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bwhile\s*\((.*)\)\s*[{;]', 13640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bswitch\s*\((.*)\)\s*{'): 13650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(pattern, line) 13660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 13670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_call = matched.group(1) # look inside the parens for function calls 13680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 13690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Except in if/for/foreach/while/switch, there should never be space 13710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # immediately inside parens (eg "f( 3, 4 )"). We make an exception 13720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # for nested parens ( (a+b) + c ). Likewise, there should never be 13730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a space before a ( when it's a function argument. I assume it's a 13740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function argument when the char before the whitespace is legal in 13750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a function name (alnum + _) and we're not starting a macro. Also ignore 13760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # pointers and references to arrays and functions coz they're too tricky: 13770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # we use a very simple way to recognize these: 13780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)(maybe-something)" or 13790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)(maybe-something," or 13800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)[something]" 13810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note that we assume the contents of [] to be short enough that 13820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # they'll never need to wrap. 13830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ( # Ignore control structures. 13840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch not search(r'\b(if|for|foreach|while|switch|return|new|delete)\b', function_call) 13850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Ignore pointers/references to functions. 13860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r' \([^)]+\)\([^)]*(\)|,$)', function_call) 13870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Ignore pointers/references to arrays. 13880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r' \([^)]+\)\[[^\]]+\]', function_call)): 13890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\w\s*\([ \t](?!\s*\\$)', function_call): # a ( used for a fn call 1390d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 13910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space after ( in function call') 13920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif search(r'\([ \t]+(?!(\s*\\)|\()', function_call): 1393d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 2, 13940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space after (') 13950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (search(r'\w\s+\(', function_call) 1396cad810f21b803229eb11403f9209855525a25d57Steve Block and not match(r'\s*(#|typedef)', function_call)): 1397d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 13980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before ( in function call') 13990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the ) is followed only by a newline or a { + newline, assume it's 14000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # part of a control statement (if/while/etc), and don't complain 14010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[^)\s]\s+\)(?!\s*$|{\s*$)', function_call): 1402d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 2, 14030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before )') 14040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef is_blank_line(line): 14070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns true if the given line is blank. 14080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch We consider a line to be blank if the line is empty or consists of 14100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch only white spaces. 14110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 14130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A line of a string. 14140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 14160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True, if the given line is blank. 14170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 14180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return not line or line.isspace() 14190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerdef detect_functions(clean_lines, line_number, function_state, error): 14226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Finds where functions start and end. 14236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Uses a simplistic algorithm assuming other style guidelines 14256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner (especially spacing) are followed. 14266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Trivial bodies are unchecked, so constructors with huge initializer lists 14276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner may be missed. 14286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Args: 14306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner clean_lines: A CleansedLines instance containing the file. 14316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner line_number: The number of the line to check. 14326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function_state: Current function name and lines in body so far. 14336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner error: The function to call with any errors found. 14346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """ 14356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Are we now past the end of a function? 143665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if function_state.end_position.row + 1 == line_number: 14376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function_state.end() 14386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # If we're in a function, don't try to detect a new one. 14406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if function_state.in_a_function: 14416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return 14426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner lines = clean_lines.lines 14446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner line = lines[line_number] 14456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner raw = clean_lines.raw_lines 14466b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner raw_line = raw[line_number] 14476b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1448cad810f21b803229eb11403f9209855525a25d57Steve Block # Lines ending with a \ indicate a macro. Don't try to check them. 1449cad810f21b803229eb11403f9209855525a25d57Steve Block if raw_line.endswith('\\'): 1450cad810f21b803229eb11403f9209855525a25d57Steve Block return 1451cad810f21b803229eb11403f9209855525a25d57Steve Block 1452cad810f21b803229eb11403f9209855525a25d57Steve Block regexp = r'\s*(\w(\w|::|\*|\&|\s|<|>|,|~|(operator\s*(/|-|=|!|\+)+))*)\(' # decls * & space::name( ... 14536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner match_result = match(regexp, line) 14546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not match_result: 14556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return 14566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # If the name is all caps and underscores, figure it's a macro and 14586b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # ignore it, unless it's TEST or TEST_F. 14596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function_name = match_result.group(1).split()[-1] 14606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if function_name != 'TEST' and function_name != 'TEST_F' and match(r'[A-Z_]+$', function_name): 14616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return 14626b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner joined_line = '' 14646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner for start_line_number in xrange(line_number, clean_lines.num_lines()): 1465f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch start_line = clean_lines.elided[start_line_number] 14666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner joined_line += ' ' + start_line.lstrip() 146765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch body_match = search(r'{|;', start_line) 146865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if body_match: 146965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch body_start_position = Position(start_line_number, body_match.start(0)) 147065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 14716b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Replace template constructs with _ so that no spaces remain in the function name, 14726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # while keeping the column numbers of other characters the same as "line". 14736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner line_with_no_templates = iteratively_replace_matches_with_char(r'<[^<>]*>', '_', line) 1474cad810f21b803229eb11403f9209855525a25d57Steve Block match_function = search(r'((\w|:|<|>|,|~|(operator\s*(/|-|=|!|\+)+))*)\(', line_with_no_templates) 14756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not match_function: 14766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return # The '(' must have been inside of a template. 14776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # Use the column numbers from the modified line to find the 14796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # function name in the original line. 14806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function = line[match_function.start(1):match_function.end(1)] 148165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch function_name_start_position = Position(line_number, match_function.start(1)) 14826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 14836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if match(r'TEST', function): # Handle TEST... macros 14846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner parameter_regexp = search(r'(\(.*\))', joined_line) 14856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if parameter_regexp: # Ignore bad syntax 14866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function += parameter_regexp.group(1) 14876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner else: 14886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function += '()' 1489cad810f21b803229eb11403f9209855525a25d57Steve Block 1490cad810f21b803229eb11403f9209855525a25d57Steve Block parameter_start_position = Position(line_number, match_function.end(1)) 149165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch parameter_end_position = close_expression(clean_lines.elided, parameter_start_position) 149265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if parameter_end_position.row == len(clean_lines.elided): 1493cad810f21b803229eb11403f9209855525a25d57Steve Block # No end was found. 1494cad810f21b803229eb11403f9209855525a25d57Steve Block return 1495cad810f21b803229eb11403f9209855525a25d57Steve Block 149665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if start_line[body_start_position.column] == ';': 149765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch end_position = Position(body_start_position.row, body_start_position.column + 1) 1498f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else: 149965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch end_position = close_expression(clean_lines.elided, body_start_position) 150065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 150165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch # Check for nonsensical positions. (This happens in test cases which check code snippets.) 150265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if parameter_end_position > body_start_position: 150365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch return 150465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 150565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch function_state.begin(function, function_name_start_position, body_start_position, end_position, 1506cad810f21b803229eb11403f9209855525a25d57Steve Block parameter_start_position, parameter_end_position, clean_lines) 15076b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return 15086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 15096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner # No body for the function (or evidence of a non-function) was found. 15106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner error(line_number, 'readability/fn_size', 5, 15116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 'Lint failed to find start of function body.') 15126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 15136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1514d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_function_lengths(clean_lines, line_number, function_state, error): 15150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Reports for long function bodies. 15160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For an overview why this is done, see: 15180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 15190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Blank/comment lines are not counted so as to avoid encouraging the removal 15210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch of vertical space and commments just to get through a lint check. 15220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NOLINT *on the last line of a function* disables this check. 15230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 15250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 15260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 15270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state: Current function name and lines in body so far. 15280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 15290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 15300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines = clean_lines.lines 15310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = lines[line_number] 15320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw = clean_lines.raw_lines 15330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_line = raw[line_number] 15340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 153565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if function_state.end_position.row == line_number: # last line 15360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'\bNOLINT\b', raw_line): 1537d0825bca7fe65beaee391d30da42e937db621564Steve Block function_state.check(error, line_number) 15380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not match(r'^\s*$', line): 15396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function_state.count(line_number) # Count non-blank/non-comment lines. 15406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 15416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 1542cad810f21b803229eb11403f9209855525a25d57Steve Blockdef _check_parameter_name_against_text(parameter, text, error): 1543cad810f21b803229eb11403f9209855525a25d57Steve Block """Checks to see if the parameter name is contained within the text. 1544cad810f21b803229eb11403f9209855525a25d57Steve Block 1545cad810f21b803229eb11403f9209855525a25d57Steve Block Return false if the check failed (i.e. an error was produced). 1546cad810f21b803229eb11403f9209855525a25d57Steve Block """ 1547cad810f21b803229eb11403f9209855525a25d57Steve Block 1548cad810f21b803229eb11403f9209855525a25d57Steve Block # Treat 'lower with underscores' as a canonical form because it is 1549cad810f21b803229eb11403f9209855525a25d57Steve Block # case insensitive while still retaining word breaks. (This ensures that 1550cad810f21b803229eb11403f9209855525a25d57Steve Block # 'elate' doesn't look like it is duplicating of 'NateLate'.) 1551cad810f21b803229eb11403f9209855525a25d57Steve Block canonical_parameter_name = parameter.lower_with_underscores_name() 1552cad810f21b803229eb11403f9209855525a25d57Steve Block 1553cad810f21b803229eb11403f9209855525a25d57Steve Block # Appends "object" to all text to catch variables that did the same (but only 1554cad810f21b803229eb11403f9209855525a25d57Steve Block # do this when the parameter name is more than a single character to avoid 1555cad810f21b803229eb11403f9209855525a25d57Steve Block # flagging 'b' which may be an ok variable when used in an rgba function). 1556cad810f21b803229eb11403f9209855525a25d57Steve Block if len(canonical_parameter_name) > 1: 1557cad810f21b803229eb11403f9209855525a25d57Steve Block text = sub(r'(\w)\b', r'\1Object', text) 1558cad810f21b803229eb11403f9209855525a25d57Steve Block canonical_text = _convert_to_lower_with_underscores(text) 1559cad810f21b803229eb11403f9209855525a25d57Steve Block 1560cad810f21b803229eb11403f9209855525a25d57Steve Block # Used to detect cases like ec for ExceptionCode. 1561cad810f21b803229eb11403f9209855525a25d57Steve Block acronym = _create_acronym(text).lower() 1562cad810f21b803229eb11403f9209855525a25d57Steve Block if canonical_text.find(canonical_parameter_name) != -1 or acronym.find(canonical_parameter_name) != -1: 1563cad810f21b803229eb11403f9209855525a25d57Steve Block error(parameter.row, 'readability/parameter_name', 5, 1564cad810f21b803229eb11403f9209855525a25d57Steve Block 'The parameter name "%s" adds no information, so it should be removed.' % parameter.name) 1565cad810f21b803229eb11403f9209855525a25d57Steve Block return False 1566cad810f21b803229eb11403f9209855525a25d57Steve Block return True 1567cad810f21b803229eb11403f9209855525a25d57Steve Block 1568cad810f21b803229eb11403f9209855525a25d57Steve Block 156981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochdef check_function_definition(filename, file_extension, clean_lines, line_number, function_state, error): 1570cad810f21b803229eb11403f9209855525a25d57Steve Block """Check that function definitions for style issues. 1571cad810f21b803229eb11403f9209855525a25d57Steve Block 1572cad810f21b803229eb11403f9209855525a25d57Steve Block Specifically, check that parameter names in declarations add information. 1573cad810f21b803229eb11403f9209855525a25d57Steve Block 1574cad810f21b803229eb11403f9209855525a25d57Steve Block Args: 157581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch filename: Filename of the file that is being processed. 157681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch file_extension: The current file extension, without the leading dot. 1577cad810f21b803229eb11403f9209855525a25d57Steve Block clean_lines: A CleansedLines instance containing the file. 1578cad810f21b803229eb11403f9209855525a25d57Steve Block line_number: The number of the line to check. 1579cad810f21b803229eb11403f9209855525a25d57Steve Block function_state: Current function name and lines in body so far. 1580cad810f21b803229eb11403f9209855525a25d57Steve Block error: The function to call with any errors found. 1581cad810f21b803229eb11403f9209855525a25d57Steve Block """ 158281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if line_number != function_state.body_start_position.row: 1583cad810f21b803229eb11403f9209855525a25d57Steve Block return 1584cad810f21b803229eb11403f9209855525a25d57Steve Block 158581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch modifiers_and_return_type = function_state.modifiers_and_return_type() 158681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if filename.find('/chromium/') != -1 and search(r'\bWEBKIT_API\b', modifiers_and_return_type): 158781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if filename.find('/chromium/public/') == -1: 158881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch error(function_state.function_name_start_position.row, 'readability/webkit_api', 5, 158981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'WEBKIT_API should only appear in the chromium public directory.') 159081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch elif not file_extension == "h": 159181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch error(function_state.function_name_start_position.row, 'readability/webkit_api', 5, 159281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'WEBKIT_API should only be used in header files.') 159381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch elif not function_state.is_declaration or search(r'\binline\b', modifiers_and_return_type): 159481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch error(function_state.function_name_start_position.row, 'readability/webkit_api', 5, 159581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'WEBKIT_API should not be used on a function with a body.') 159681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch elif function_state.is_pure: 159781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch error(function_state.function_name_start_position.row, 'readability/webkit_api', 5, 159881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'WEBKIT_API should not be used with a pure virtual function.') 159981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 160081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # Do checks specific to function declaractions. 160181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if not function_state.is_declaration: 160281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return 1603cad810f21b803229eb11403f9209855525a25d57Steve Block parameter_list = function_state.parameter_list() 1604cad810f21b803229eb11403f9209855525a25d57Steve Block for parameter in parameter_list: 1605cad810f21b803229eb11403f9209855525a25d57Steve Block if not parameter.name: 1606cad810f21b803229eb11403f9209855525a25d57Steve Block continue 1607cad810f21b803229eb11403f9209855525a25d57Steve Block 1608cad810f21b803229eb11403f9209855525a25d57Steve Block # Check the parameter name against the function name for single parameter set functions. 1609cad810f21b803229eb11403f9209855525a25d57Steve Block if len(parameter_list) == 1 and match('set[A-Z]', function_state.current_function): 1610cad810f21b803229eb11403f9209855525a25d57Steve Block trimmed_function_name = function_state.current_function[len('set'):] 1611cad810f21b803229eb11403f9209855525a25d57Steve Block if not _check_parameter_name_against_text(parameter, trimmed_function_name, error): 1612cad810f21b803229eb11403f9209855525a25d57Steve Block continue # Since an error was noted for this name, move to the next parameter. 1613cad810f21b803229eb11403f9209855525a25d57Steve Block 1614cad810f21b803229eb11403f9209855525a25d57Steve Block # Check the parameter name against the type. 1615cad810f21b803229eb11403f9209855525a25d57Steve Block if not _check_parameter_name_against_text(parameter, parameter.type, error): 1616cad810f21b803229eb11403f9209855525a25d57Steve Block continue # Since an error was noted for this name, move to the next parameter. 1617cad810f21b803229eb11403f9209855525a25d57Steve Block 1618cad810f21b803229eb11403f9209855525a25d57Steve Block 16196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerdef check_pass_ptr_usage(clean_lines, line_number, function_state, error): 16206b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """Check for proper usage of Pass*Ptr. 16216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 16226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Currently this is limited to detecting declarations of Pass*Ptr 16236b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner variables inside of functions. 16246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 16256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner Args: 16266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner clean_lines: A CleansedLines instance containing the file. 16276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner line_number: The number of the line to check. 16286b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner function_state: Current function name and lines in body so far. 16296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner error: The function to call with any errors found. 16306b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner """ 16316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if not function_state.in_a_function: 16326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return 16336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 16346b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner lines = clean_lines.lines 16356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner line = lines[line_number] 163665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if line_number > function_state.body_start_position.row: 16376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner matched_pass_ptr = match(r'^\s*Pass([A-Z][A-Za-z]*)Ptr<', line) 16386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if matched_pass_ptr: 16396b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner type_name = 'Pass%sPtr' % matched_pass_ptr.group(1) 16406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner error(line_number, 'readability/pass_ptr', 5, 16416b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 'Local variables should never be %s (see ' 16426b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 'http://webkit.org/coding/RefPtr.html).' % type_name) 16430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1645d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_spacing(file_extension, clean_lines, line_number, error): 16460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for the correctness of various spacing issues in the code. 16470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Things we check for: spaces around operators, spaces after 16490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if/for/while/switch, no spaces around parens in function calls, two 16500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch spaces between code and comment, don't start a block with a blank 16510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line, don't end a function with a blank line, don't have too many 16520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch blank lines in a row. 16530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 1655d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The current file extension, without the leading dot. 16560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 16570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 16580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 16590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 16600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw = clean_lines.raw_lines 16620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = raw[line_number] 16630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Before nixing comments, check if the line is blank for no good 16650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # reason. This includes the first line after a block is opened, and 16660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # blank lines at the end of a function (ie, right before a line like '}'). 16670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if is_blank_line(line): 16680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = clean_lines.elided 16690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = elided[line_number - 1] 16700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_brace = previous_line.rfind('{') 16710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: Don't complain if line before blank line, and line after, 16720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # both start with alnums and are indented the same amount. 16730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This ignores whitespace at the start of a namespace block 16740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because those are not usually indented. 16750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (previous_brace != -1 and previous_line[previous_brace:].find('}') == -1 16760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and previous_line[:previous_brace].find('namespace') == -1): 16770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # OK, we have a blank line at the start of a code block. Before we 16780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # complain, we check if it is an exception to the rule: The previous 16790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # non-empty line has the parameters of a function header that are indented 16800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 4 spaces (because they did not fit in a 80 column line when placed on 16810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same line as the function name). We also check for the case where 16820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the previous line is indented 6 spaces, which may happen when the 16830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # initializers of a constructor do not fit into a 80 column line. 16840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = False 16850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r' {6}\w', previous_line): # Initializer list? 16860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We are looking for the opening column of initializer list, which 16870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # should be indented 4 spaces to cause 6 space indentation afterwards. 16880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch search_position = line_number - 2 16890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (search_position >= 0 16900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and match(r' {6}\w', elided[search_position])): 16910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch search_position -= 1 16920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = (search_position >= 0 16930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and elided[search_position][:5] == ' :') 16940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 16950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Search for the function arguments or an initializer list. We use a 16960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # simple heuristic here: If the line is indented 4 spaces; and we have a 16970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # closing paren, without the opening paren, followed by an opening brace 16980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or colon (for initializer lists) we assume that it is the last line of 16990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a function header. If we have a colon indented 4 spaces, it is an 17000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # initializer list. 17010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = (match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', 17020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line) 17030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or match(r' {4}:', previous_line)) 17040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not exception: 1706d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/blank_line', 2, 17070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Blank line at the start of a code block. Is this needed?') 17080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This doesn't ignore whitespace at the end of a namespace block 17090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because that is too hard without pairing open/close braces; 17100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # however, a special exception is made for namespace closing 17110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # brackets which have a comment containing "namespace". 17120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 17130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Also, ignore blank lines at the end of a block in a long if-else 17140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # chain, like this: 17150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if (condition1) { 17160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # // Something followed by a blank line 17170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 17180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } else if (condition2) { 17190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # // Something else 17200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } 17210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_number + 1 < clean_lines.num_lines(): 17220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch next_line = raw[line_number + 1] 17230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (next_line 17240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and match(r'\s*}', next_line) 17250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and next_line.find('namespace') == -1 17260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and next_line.find('} else ') == -1): 1727d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/blank_line', 3, 17280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Blank line at the end of a code block. Is this needed?') 17290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 173081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # Next, we check for proper spacing with respect to comments. 17310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch comment_position = line.find('//') 17320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if comment_position != -1: 17330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if the // may be in quotes. If so, ignore it 17340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 17350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (line.count('"', 0, comment_position) - line.count('\\"', 0, comment_position)) % 2 == 0: # not in quotes 1736d0825bca7fe65beaee391d30da42e937db621564Steve Block # Allow one space before end of line comment. 1737d0825bca7fe65beaee391d30da42e937db621564Steve Block if (not match(r'^\s*$', line[:comment_position]) 1738d0825bca7fe65beaee391d30da42e937db621564Steve Block and (comment_position >= 1 1739d0825bca7fe65beaee391d30da42e937db621564Steve Block and ((line[comment_position - 1] not in string.whitespace) 17400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or (comment_position >= 2 1741d0825bca7fe65beaee391d30da42e937db621564Steve Block and line[comment_position - 2] in string.whitespace)))): 1742d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comments', 5, 1743d0825bca7fe65beaee391d30da42e937db621564Steve Block 'One space before end of line comments') 17440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There should always be a space between the // and the comment 17450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch commentend = comment_position + 2 17460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if commentend < len(line) and not line[commentend] == ' ': 17470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # but some lines are exceptions -- e.g. if they're big 17480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # comment delimiters like: 17490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # //---------------------------------------------------------- 17500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or they begin with multiple slashes followed by a space: 17510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # //////// Header comment 17520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = (search(r'[=/-]{4,}\s*$', line[commentend:]) 17530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or search(r'^/+ ', line[commentend:])) 17540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 1755d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comments', 4, 17560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Should have a space between // and comment') 17570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 175881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # There should only be one space after punctuation in a comment. 175981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if search('[.!?,;:]\s\s', line[comment_position:]): 176081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch error(line_number, 'whitespace/comments', 5, 176181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'Should only a single space after a punctuation in a comment.') 176281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 17630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # get rid of comments and strings 17640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't try to do spacing checks for operator methods 1766e14391e94c850b8bd03680c23b38978db68687a8John Reck line = sub(r'operator(==|!=|<|<<|<=|>=|>>|>|\+=|-=|\*=|/=|%=|&=|\|=|^=|<<=|>>=)\(', 'operator\(', line) 1767643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Don't try to do spacing checks for #include or #import statements at 1768643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # minimum because it messes up checks for spacing around / 1769643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if match(r'\s*#\s*(?:include|import)', line): 1770cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return 1771cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if search(r'[\w.]=[\w.]', line): 1772d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 17730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing spaces around =') 17740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1775cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block # FIXME: It's not ok to have spaces around binary operators like . 17760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You should always have whitespace around binary operators. 17780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Alas, we can't test < or > because they're legitimately used sans spaces 17790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # (a->b, vector<int> a). The only time we can tell is a < with no >, and 17800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # only if it's not template params list spilling into the next line. 1781231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block matched = search(r'[^<>=!\s](==|!=|\+=|-=|\*=|/=|/|\|=|&=|<<=|>>=|<=|>=|\|\||\||&&|>>|<<)[^<>=!\s]', line) 17820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 17830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note that while it seems that the '<[^<]*' term in the following 17840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # regexp could be simplified to '<.*', which would indeed match 17850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same class of strings, the [^<] means that searching for the 17860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # regexp takes linear rather than quadratic time. 17870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'<[^<]*,\s*$', line): # template params spill 17880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line) 17890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1790d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 3, 17910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing spaces around %s' % matched.group(1)) 17920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There shouldn't be space around unary operators 17940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) 17950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1796d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 17970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space for operator %s' % matched.group(1)) 17980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # A pet peeve of mine: no spaces after an if, while, switch, or for 18000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r' (if\(|for\(|foreach\(|while\(|switch\()', line) 18010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1802d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 5, 18030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before ( in %s' % matched.group(1)) 18040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For if/for/foreach/while/switch, the left and right parens should be 18060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # consistent about how many spaces are inside the parens, and 18070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # there should either be zero or one spaces inside the parens. 18080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We don't want: "if ( foo)" or "if ( foo )". 18090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. 181006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen matched = search(r'\b(?P<statement>if|for|foreach|while|switch)\s*\((?P<remainder>.*)$', line) 18110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1812d0825bca7fe65beaee391d30da42e937db621564Steve Block statement = matched.group('statement') 181306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen condition, rest = up_to_unmatched_closing_paren(matched.group('remainder')) 1814d0825bca7fe65beaee391d30da42e937db621564Steve Block if condition is not None: 1815d0825bca7fe65beaee391d30da42e937db621564Steve Block condition_match = search(r'(?P<leading>[ ]*)(?P<separator>.).*[^ ]+(?P<trailing>[ ]*)', condition) 1816d0825bca7fe65beaee391d30da42e937db621564Steve Block if condition_match: 1817d0825bca7fe65beaee391d30da42e937db621564Steve Block n_leading = len(condition_match.group('leading')) 1818d0825bca7fe65beaee391d30da42e937db621564Steve Block n_trailing = len(condition_match.group('trailing')) 181906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if n_leading != 0: 182006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen for_exception = statement == 'for' and condition.startswith(' ;') 1821d0825bca7fe65beaee391d30da42e937db621564Steve Block if not for_exception: 1822d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 5, 182306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 'Extra space after ( in %s' % statement) 182406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if n_trailing != 0: 182506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen for_exception = statement == 'for' and condition.endswith('; ') 182606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if not for_exception: 182706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen error(line_number, 'whitespace/parens', 5, 182806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 'Extra space before ) in %s' % statement) 1829d0825bca7fe65beaee391d30da42e937db621564Steve Block 1830d0825bca7fe65beaee391d30da42e937db621564Steve Block # Do not check for more than one command in macros 1831f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch in_preprocessor_directive = match(r'\s*#', line) 1832f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not in_preprocessor_directive and not match(r'((\s*{\s*}?)|(\s*;?))\s*\\?$', rest): 1833d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 1834d0825bca7fe65beaee391d30da42e937db621564Steve Block 'More than one command on the same line in %s' % statement) 18350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You should always have a space after a comma (either as fn arg or operator) 18370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r',[^\s]', line): 1838d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comma', 3, 18390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space after ,') 18400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 184106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen matched = search(r'^\s*(?P<token1>[a-zA-Z0-9_\*&]+)\s\s+(?P<token2>[a-zA-Z0-9_\*&]+)', line) 184206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if matched: 184306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen error(line_number, 'whitespace/declaration', 3, 184406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 'Extra space between %s and %s' % (matched.group('token1'), matched.group('token2'))) 184506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 1846d0825bca7fe65beaee391d30da42e937db621564Steve Block if file_extension == 'cpp': 18470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # C++ should have the & or * beside the type not the variable name. 1848dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block matched = match(r'\s*\w+(?<!\breturn|\bdelete)\s+(?P<pointer_operator>\*|\&)\w+', line) 18490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1850d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/declaration', 3, 18510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Declaration has space between type name and %s in %s' % (matched.group('pointer_operator'), matched.group(0).strip())) 18520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1853d0825bca7fe65beaee391d30da42e937db621564Steve Block elif file_extension == 'c': 18540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # C Pointer declaration should have the * beside the variable not the type name. 18550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'^\s*\w+\*\s+\w+', line) 18560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1857d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/declaration', 3, 18580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Declaration has space between * and variable name in %s' % matched.group(0).strip()) 18590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Next we will look for issues with function calls. 1861d0825bca7fe65beaee391d30da42e937db621564Steve Block check_spacing_for_function_call(line, line_number, error) 18620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Except after an opening paren, you should have spaces before your braces. 18640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # And since you should never have braces at the beginning of a line, this is 18650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # an easy test. 18660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[^ ({]{', line): 1867d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 18680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before {') 18690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Make sure '} else {' has spaces. 18710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'}else', line): 1872d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 18730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before else') 18740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You shouldn't have spaces before your brackets, except maybe after 18760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 'delete []' or 'new char * []'. 18770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\w\s+\[', line) and not search(r'delete\s+\[', line): 1878d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 18790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before [') 18800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You shouldn't have a space before a semicolon at the end of the line. 18820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There's a special case for "for" since the style guide allows space before 18830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the semicolon there. 18840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r':\s*;\s*$', line): 1885d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 18860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Semicolon defining empty statement. Use { } instead.') 18870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif search(r'^\s*;\s*$', line): 1888d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 18890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line contains only semicolon. If this should be an empty statement, ' 18900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'use { } instead.') 18910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\s+;\s*$', line) and not search(r'\bfor\b', line)): 1892d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 18930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before last semicolon. If this should be an empty ' 18940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'statement, use { } instead.') 18950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\b(for|while)\s*\(.*\)\s*;\s*$', line) 18960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('(') == line.count(')') 18970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Allow do {} while(); 18980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'}\s*while', line)): 1899d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 19000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Semicolon defining empty statement for this loop. Use { } instead.') 19010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_previous_non_blank_line(clean_lines, line_number): 19040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Return the most recent non-blank line and its line number. 19050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 19070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file contents. 19080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 19090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 19110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch A tuple with two elements. The first element is the contents of the last 19120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch non-blank line before the current line, or the empty string if this is the 19130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch first non-blank line. The second is the line number of that line, or -1 19140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if this is the first non-blank line. 19150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 19160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number - 1 19180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while previous_line_number >= 0: 19190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.elided[previous_line_number] 19200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_blank_line(previous_line): # if not a blank line... 19210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (previous_line, previous_line_number) 19220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number -= 1 19230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ('', -1) 19240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1926d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error): 19270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for indentation errors inside of namespaces. 19280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 19300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 19310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 19320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 1933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 1934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 19350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 19360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 19370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 19390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch namespace_match = match(r'(?P<namespace_indentation>\s*)namespace\s+\S+\s*{\s*$', line) 19410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not namespace_match: 19420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 19430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1944cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block current_indentation_level = len(namespace_match.group('namespace_indentation')) 1945cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if current_indentation_level > 0: 1946643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Don't warn about an indented namespace if we already warned about indented code. 1947643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not file_state.did_inside_namespace_indent_warning(): 1948d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/indent', 4, 1949643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 'namespace should never be indented.') 1950cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return 1951cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = False; 19520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 1953cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block in_preprocessor_directive = False; 1954cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block for current_line in clean_lines.elided[line_number + 1:]: 1955cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block line_offset += 1 1956cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not current_line.strip(): 1957cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block continue 1958cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not current_indentation_level: 1959cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not (in_preprocessor_directive or looking_for_semicolon): 1960643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not match(r'\S', current_line) and not file_state.did_inside_namespace_indent_warning(): 1961643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state.set_did_inside_namespace_indent_warning() 1962d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 1963cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 'Code inside a namespace should not be indented.') 1964cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if in_preprocessor_directive or (current_line.strip()[0] == '#'): # This takes care of preprocessor directive syntax. 1965cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block in_preprocessor_directive = current_line[-1] == '\\' 1966cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block else: 1967cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = ((current_line.find(';') == -1) and (current_line.strip()[-1] != '}')) or (current_line[-1] == '\\') 1968cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block else: 1969cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = False; # If we have a brace we may not need a semicolon. 1970cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block current_indentation_level += current_line.count('{') - current_line.count('}') 1971cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if current_indentation_level < 0: 1972cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block break; 19730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1974f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1975f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef check_using_std(clean_lines, line_number, file_state, error): 1976231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """Looks for 'using std::foo;' statements which should be replaced with 'using namespace std;'. 1977231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1978231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Args: 1979231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block clean_lines: A CleansedLines instance containing the file. 1980231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line_number: The number of the line to check. 1981f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state: A _FileState instance which maintains information about 1982f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch the state of things in the file. 1983231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block error: The function to call with any errors found. 1984231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """ 1985231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1986231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block # This check doesn't apply to C or Objective-C implementation files. 1987f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if file_state.is_c_or_objective_c(): 1988231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1989231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1990231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line = clean_lines.elided[line_number] # Get rid of comments and strings. 1991231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1992231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block using_std_match = match(r'\s*using\s+std::(?P<method_name>\S+)\s*;\s*$', line) 1993231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if not using_std_match: 1994231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1995231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1996231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block method_name = using_std_match.group('method_name') 1997d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/using_std', 4, 1998231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block "Use 'using namespace std;' instead of 'using std::%s;'." % method_name) 1999231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2000231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2001f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef check_max_min_macros(clean_lines, line_number, file_state, error): 2002231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """Looks use of MAX() and MIN() macros that should be replaced with std::max() and std::min(). 2003231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2004231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Args: 2005231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block clean_lines: A CleansedLines instance containing the file. 2006231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line_number: The number of the line to check. 2007f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state: A _FileState instance which maintains information about 2008f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch the state of things in the file. 2009231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block error: The function to call with any errors found. 2010231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """ 2011231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2012231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block # This check doesn't apply to C or Objective-C implementation files. 2013f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if file_state.is_c_or_objective_c(): 2014231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 2015231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2016231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line = clean_lines.elided[line_number] # Get rid of comments and strings. 2017231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2018231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macros_search = search(r'\b(?P<max_min_macro>(MAX|MIN))\s*\(', line) 2019231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if not max_min_macros_search: 2020231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 2021231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2022231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macro = max_min_macros_search.group('max_min_macro') 2023231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macro_lower = max_min_macro.lower() 2024d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/max_min_macros', 4, 2025231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 'Use std::%s() or std::%s<type>() instead of the %s() macro.' 2026231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block % (max_min_macro_lower, max_min_macro_lower, max_min_macro)) 2027231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2028231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2029d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_switch_indentation(clean_lines, line_number, error): 20300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for indentation errors inside of switch statements. 20310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 20330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 20340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 20350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 20360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 20370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 20390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch_match = match(r'(?P<switch_indentation>\s*)switch\s*\(.+\)\s*{\s*$', line) 20410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not switch_match: 20420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 20430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch_indentation = switch_match.group('switch_indentation') 20450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch inner_indentation = switch_indentation + ' ' * 4 20460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 20470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_nested_switch = False 20480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for current_line in clean_lines.elided[line_number + 1:]: 20500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset += 1 20510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip not only empty lines but also those with preprocessor directives. 20530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line.strip() == '' or current_line.startswith('#'): 20540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 20550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*switch\s*\(.+\)\s*{\s*$', current_line): 20570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Complexity alarm - another switch statement nested inside the one 20580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that we're currently testing. We'll need to track the extent of 20590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that inner switch if the upcoming label tests are still supposed 20600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # to work correctly. Let's not do that; instead, we'll finish 20610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # checking this line, and then leave it like that. Assuming the 20620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # indentation is done consistently (even if incorrectly), this will 20630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # still catch all indentation issues in practice. 20640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_nested_switch = True 20650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line); 20670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation = current_indentation_match.group('indentation') 20680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remaining_line = current_indentation_match.group('remaining_line') 20690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # End the check at the end of the switch statement. 20710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if remaining_line.startswith('}') and current_indentation == switch_indentation: 20720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 20730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Case and default branches should not be indented. The regexp also 20740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # catches single-line cases like "default: break;" but does not trigger 20750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # on stuff like "Document::Foo();". 20760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif match(r'(default|case\s+.*)\s*:([^:].*)?$', remaining_line): 20770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation != switch_indentation: 2078d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 20790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'A case label should not be indented, but line up with its switch statement.') 20800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't throw an error for multiple badly indented labels, 20810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one should be enough to figure out the problem. 20820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 20830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We ignore goto labels at the very beginning of a line. 20840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif match(r'\w+\s*:\s*$', remaining_line): 20850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 20860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # It's not a goto label, so check if it's indented at least as far as 20870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the switch statement plus one more level of indentation. 20880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not current_indentation.startswith(inner_indentation): 2089d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 20900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Non-label code inside switch statements should be indented.') 20910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't throw an error for multiple badly indented statements, 20920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one should be enough to figure out the problem. 20930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 20940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if encountered_nested_switch: 20960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 20970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2099d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_braces(clean_lines, line_number, error): 21000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for misplaced braces (e.g. at the end of line). 21010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 21030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 21040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 21050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 21060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 21070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 21090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*{\s*$', line): 21110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We allow an open brace to start a line in the case where someone 21120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # is using braces for function definition or in a block to 21130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # explicitly create a new scope, which is commonly used to control 21140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the lifetime of stack-allocated variables. We don't detect this 21150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # perfectly: we just don't complain if the last non-whitespace 21160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # character on the previous non-blank line is ';', ':', '{', '}', 21170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # ')', or ') const' and doesn't begin with 'if|for|while|switch|else'. 21180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We also allow '#' for #endif and '=' for array initialization. 21190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = get_previous_non_blank_line(clean_lines, line_number)[0] 21200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ((not search(r'[;:}{)=]\s*$|\)\s*const\s*$', previous_line) 21210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or search(r'\b(if|for|foreach|while|switch|else)\b', previous_line)) 21220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and previous_line.find('#') < 0): 2123d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 21240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'This { should be at the end of the previous line') 21250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\)\s*(const\s*)?{\s*$', line) 21260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('(') == line.count(')') 2127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and not search(r'\b(if|for|foreach|while|switch)\b', line) 2128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and not match(r'\s+[A-Z_][A-Z_0-9]+\b', line)): 2129d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 21300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Place brace on its own line for function definitions.') 21310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (match(r'\s*}\s*(else\s*({\s*)?)?$', line) and line_number > 1): 21330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We check if a closed brace has started a line to see if a 21340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one line control statement was previous. 21350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.elided[line_number - 2] 213681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch last_open_brace = previous_line.rfind('{') 213781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if (last_open_brace != -1 and previous_line.find('}', last_open_brace) == -1 21380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and search(r'\b(if|for|foreach|while|else)\b', previous_line)): 2139d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 21400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'One line control clauses should not use braces.') 21410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # An else clause should be on the same line as the preceding closing brace. 21430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*else\s*', line): 21440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = get_previous_non_blank_line(clean_lines, line_number)[0] 21450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*}\s*$', previous_line): 2146d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 21470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else should appear on the same line as the preceding }') 21480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Likewise, an else should never have the else clause on the same line 21500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\belse [^\s{]', line) and not search(r'\belse if\b', line): 2151d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 21520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Else clause should never be on same line as else (use 2 lines)') 21530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In the same way, a do/while should never be on one line 21550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*do [^\s{]', line): 2156d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 21570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'do/while clauses should not be on a single line') 21580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Braces shouldn't be followed by a ; unless they're defining a struct 21600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or initializing an array. 21610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We can't tell in general, but we can for some common cases. 21620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number 21630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while True: 21640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (previous_line, previous_line_number) = get_previous_non_blank_line(clean_lines, previous_line_number) 21650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s+{.*}\s*;', line) and not previous_line.count(';'): 21660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = previous_line + line 21670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 21680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 21690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (search(r'{.*}\s*;', line) 21700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('{') == line.count('}') 21710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'struct|class|enum|\s*=\s*{', line)): 2172d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/braces', 4, 21730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "You don't need a ; after a }") 21740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2176d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_exit_statement_simplifications(clean_lines, line_number, error): 21770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for else or else-if statements that should be written as an 21780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if statement when the prior if concludes with a return, break, continue or 21790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch goto statement. 21800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 21820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 21830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 21840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 21850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 21860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 21880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else_match = match(r'(?P<else_indentation>\s*)(\}\s*)?else(\s+if\s*\(|(?P<else>\s*(\{\s*)?\Z))', line) 21900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not else_match: 21910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 21920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else_indentation = else_match.group('else_indentation') 21940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch inner_indentation = else_indentation + ' ' * 4 21950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_lines = clean_lines.elided[:line_number] 21970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_lines.reverse() 21980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 21990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_exit_statement = False 22000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for current_line in previous_lines: 22020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset -= 1 22030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip not only empty lines but also those with preprocessor directives 22050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # and goto labels. 22060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line.strip() == '' or current_line.startswith('#') or match(r'\w+\s*:\s*$', current_line): 22070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 22080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip lines with closing braces on the original indentation level. 22100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Even though the styleguide says they should be on the same line as 22110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the "else if" statement, we also want to check for instances where 22120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the current code does not comply with the coding style. Thus, ignore 22130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # these lines and proceed to the line before that. 22140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line == else_indentation + '}': 22150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 22160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line); 22180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation = current_indentation_match.group('indentation') 22190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remaining_line = current_indentation_match.group('remaining_line') 22200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # As we're going up the lines, the first real statement to encounter 22220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # has to be an exit statement (return, break, continue or goto) - 22230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # otherwise, this check doesn't apply. 22240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not encountered_exit_statement: 22250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We only want to find exit statements if they are on exactly 22260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same level of indentation as expected from the code inside 22270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the block. If the indentation doesn't strictly match then we 22280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # might have a nested if or something, which must be ignored. 22290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation != inner_indentation: 22300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 22310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(return(\W+.*)|(break|continue)\s*;|goto\s*\w+;)$', remaining_line): 22320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_exit_statement = True 22330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 22340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 22350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # When code execution reaches this point, we've found an exit statement 22370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # as last statement of the previous block. Now we only need to make 22380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # sure that the block belongs to an "if", then we can throw an error. 22390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip lines with opening braces on the original indentation level, 22410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # similar to the closing braces check above. ("if (condition)\n{") 22420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line == else_indentation + '{': 22430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 22440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip everything that's further indented than our "else" or "else if". 22460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation.startswith(else_indentation) and current_indentation != else_indentation: 22470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 22480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # So we've got a line with same (or less) indentation. Is it an "if"? 22500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If yes: throw an error. If no: don't throw an error. 22510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Whatever the outcome, this is the end of our loop. 22520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'if\s*\(', remaining_line): 22530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if else_match.start('else') != -1: 2254d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'readability/control_flow', 4, 22550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else statement can be removed when the prior "if" ' 22560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'concludes with a return, break, continue or goto statement.') 22570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 2258d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'readability/control_flow', 4, 22590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else if statement should be written as an if statement ' 22600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'when the prior "if" concludes with a return, break, ' 22610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'continue or goto statement.') 22620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 22630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef replaceable_check(operator, macro, line): 22660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Determine whether a basic CHECK can be replaced with a more specific one. 22670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example suggest using CHECK_EQ instead of CHECK(a == b) and 22690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. 22700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 22720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch operator: The C++ operator used in the CHECK. 22730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch macro: The CHECK or EXPECT macro being called. 22740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The current source line. 22750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 22770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True if the CHECK can be replaced with a more specific one. 22780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 22790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This matches decimal and hex integers, strings, and chars (in that order). 22810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' 22820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Expression to match two sides of the operator with something that 22840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # looks like a literal, since CHECK(x == iterator) won't compile. 22850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This means we can't catch all the cases where a more specific 22860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # CHECK is possible, but it's less annoying than dealing with 22870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # extraneous warnings. 22880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_this = (r'\s*' + macro + r'\((\s*' + 22890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_constant + r'\s*' + operator + r'[^<>].*|' 22900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'.*[^<>]' + operator + r'\s*' + match_constant + 22910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s*\))') 22920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't complain about CHECK(x == NULL) or similar because 22940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # CHECK_EQ(x, NULL) won't compile (requires a cast). 22950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Also, don't complain about more complex boolean expressions 22960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # involving && or || such as CHECK(a == b || c == d). 22970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return match(match_this, line) and not search(r'NULL|&&|\|\|', line) 22980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2300d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_check(clean_lines, line_number, error): 23010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks the use of CHECK and EXPECT macros. 23020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 23040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 23050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 23060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 23070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 23080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Decide the set of replacement macros that should be suggested 23100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 23110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro = '' 23120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for macro in _CHECK_MACROS: 23130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if raw_lines[line_number].find(macro) >= 0: 23140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro = macro 23150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 23160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not current_macro: 23170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' 23180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 23190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # get rid of comments and strings 23210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. 23230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for operator in ['==', '!=', '>=', '>', '<=', '<']: 23240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if replaceable_check(operator, current_macro, line): 2325d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/check', 2, 23260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider using %s instead of %s(a %s b)' % ( 23270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT[current_macro][operator], 23280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro, operator)) 23290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 23300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2332d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_comparisons_to_zero(clean_lines, line_number, error): 23330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Get the line without comments and strings. 23340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 23350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Include NULL here so that users don't have to convert NULL to 0 first and then get this error. 23370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[=!]=\s*(NULL|0|true|false)\W', line) or search(r'\W(NULL|0|true|false)\s*[=!]=', line): 2338d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/comparison_to_zero', 5, 23390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.') 23400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2342f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef check_for_null(clean_lines, line_number, file_state, error): 23430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This check doesn't apply to C or Objective-C implementation files. 2344f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if file_state.is_c_or_objective_c(): 23450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 23460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 2348d0825bca7fe65beaee391d30da42e937db621564Steve Block 23495af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke # Don't warn about NULL usage in g_*(). See Bug 32858 and 39372. 23505af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if search(r'\bg(_[a-z]+)+\b', line): 23515af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke return 23525af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke 23535af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke # Don't warn about NULL usage in gst_*_many(). See Bug 39740 23545af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke if search(r'\bgst_\w+_many\b', line): 2355d0825bca7fe65beaee391d30da42e937db621564Steve Block return 2356d0825bca7fe65beaee391d30da42e937db621564Steve Block 2357692e5dbf12901edacf14812a6fae25462920af42Steve Block # Don't warn about NULL usage in g_str{join,concat}(). See Bug 34834 2358692e5dbf12901edacf14812a6fae25462920af42Steve Block if search(r'\bg_str(join|concat)\b', line): 2359692e5dbf12901edacf14812a6fae25462920af42Steve Block return 2360692e5dbf12901edacf14812a6fae25462920af42Steve Block 23610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen # Don't warn about NULL usage in gdk_pixbuf_save_to_*{join,concat}(). See Bug 43090. 23620617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen if search(r'\bgdk_pixbuf_save_to\w+\b', line): 23630617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen return 23640617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen 2365cad810f21b803229eb11403f9209855525a25d57Steve Block # Don't warn about NULL usage in gtk_widget_style_get(). See Bug 51758. 2366cad810f21b803229eb11403f9209855525a25d57Steve Block if search(r'\bgtk_widget_style_get\(\w+\b', line): 2367cad810f21b803229eb11403f9209855525a25d57Steve Block return 2368cad810f21b803229eb11403f9209855525a25d57Steve Block 23690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNULL\b', line): 2370d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.') 23710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 23720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.raw_lines[line_number] 23740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # See if NULL occurs in any comments in the line. If the search for NULL using the raw line 23750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # matches, then do the check with strings collapsed to avoid giving errors for 23760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # NULLs occurring in strings. 23770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNULL\b', line) and search(r'\bNULL\b', CleansedLines.collapse_strings(line)): 23782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block error(line_number, 'readability/null', 4, 'Use 0 or null instead of NULL (even in *comments*).') 23790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_line_width(line): 23810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Determines the width of the line in column positions. 23820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 23840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A string, which may be a Unicode string. 23850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 23870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The width of the line in column positions, accounting for Unicode 23880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch combining characters and wide characters. 23890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 23900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if isinstance(line, unicode): 23910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width = 0 23920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for c in unicodedata.normalize('NFC', line): 23930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if unicodedata.east_asian_width(c) in ('W', 'F'): 23940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width += 2 23950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not unicodedata.combining(c): 23960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width += 1 23970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return width 23980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(line) 23990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24010617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsendef check_style(clean_lines, line_number, file_extension, class_state, file_state, error): 24020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks rules from the 'C++ style rules' section of cppguide.html. 24030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Most of these rules are hard to test (naming, comment style), but we 24050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch do what we can. In particular we check for 4-space indents, line lengths, 24060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tab usage, spaces inside code, etc. 24070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 24090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 24100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 24110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (without the dot) of the filename. 24120617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen class_state: A _ClassState instance which maintains information about 24130617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen the current stack of nested class declarations being parsed. 2414643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 2415643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 24160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 24170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 24180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 24200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = raw_lines[line_number] 24210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.find('\t') != -1: 2423d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/tab', 1, 24240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Tab found; better to use spaces') 24250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # One or three blank spaces at the beginning of the line is weird; it's 24270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # hard to reconcile that with 4-space indents. 24280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # NOTE: here are the conditions rob pike used for his tests. Mine aren't 24290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces 24300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(RLENGTH > 20) complain = 0; 24310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match($0, " +(error|private|public|protected):")) complain = 0; 24320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "&& *$")) complain = 0; 24330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "\\|\\| *$")) complain = 0; 24340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "[\",=><] *$")) complain = 0; 24350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match($0, " <<")) complain = 0; 24360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, " +for \\(")) complain = 0; 24370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(prevodd && match(prevprev, " +for \\(")) complain = 0; 24380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch initial_spaces = 0 24390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cleansed_line = clean_lines.elided[line_number] 24400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while initial_spaces < len(line) and line[initial_spaces] == ' ': 24410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch initial_spaces += 1 24420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line and line[-1].isspace(): 2443d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/end_of_line', 4, 24440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line ends in whitespace. Consider deleting these extra spaces.') 24450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There are certain situations we allow one space, notably for labels 24460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif ((initial_spaces >= 1 and initial_spaces <= 3) 24470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not match(r'\s*\w+\s*:\s*$', cleansed_line)): 2448d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/indent', 3, 24490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Weird number of spaces at line-start. ' 24500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Are you using a 4-space indent?') 24510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Labels should always be indented at least one space. 24520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not initial_spaces and line[:2] != '//': 24530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch label_match = match(r'(?P<label>[^:]+):\s*$', line) 24540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if label_match: 24560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch label = label_match.group('label') 24570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only throw errors for stuff that is definitely not a goto label, 24580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because goto labels can in fact occur at the start of the line. 24590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if label in ['public', 'private', 'protected'] or label.find(' ') != -1: 2460d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/labels', 4, 24610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Labels should always be indented at least one space. ' 24620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'If this is a member-initializer list in a constructor, ' 24630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'the colon should be on the line after the definition header.') 24640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (cleansed_line.count(';') > 1 24660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # for loops are allowed two ;'s (and may run over two lines). 24670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and cleansed_line.find('for') == -1 24680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (get_previous_non_blank_line(clean_lines, line_number)[0].find('for') == -1 24690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or get_previous_non_blank_line(clean_lines, line_number)[0].find(';') != -1) 24700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # It's ok to have many commands in a switch case that fits in 1 line 24710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not ((cleansed_line.find('case ') != -1 24720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or cleansed_line.find('default:') != -1) 2473d0825bca7fe65beaee391d30da42e937db621564Steve Block and cleansed_line.find('break;') != -1) 24740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen # Also it's ok to have many commands in trivial single-line accessors in class definitions. 24750617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen and not (match(r'.*\(.*\).*{.*.}', line) 24760617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen and class_state.classinfo_stack 24770617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen and line.count('{') == line.count('}')) 2478d0825bca7fe65beaee391d30da42e937db621564Steve Block and not cleansed_line.startswith('#define ')): 2479d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 24800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'More than one command on the same line') 24810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if cleansed_line.strip().endswith('||') or cleansed_line.strip().endswith('&&'): 2483d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 24840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Boolean expressions that span multiple lines should have their ' 24850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'operators on the left side of the line instead of the right side.') 24860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Some more style checks 2488d0825bca7fe65beaee391d30da42e937db621564Steve Block check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error) 2489f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch check_using_std(clean_lines, line_number, file_state, error) 2490f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch check_max_min_macros(clean_lines, line_number, file_state, error) 2491d0825bca7fe65beaee391d30da42e937db621564Steve Block check_switch_indentation(clean_lines, line_number, error) 2492d0825bca7fe65beaee391d30da42e937db621564Steve Block check_braces(clean_lines, line_number, error) 2493d0825bca7fe65beaee391d30da42e937db621564Steve Block check_exit_statement_simplifications(clean_lines, line_number, error) 2494d0825bca7fe65beaee391d30da42e937db621564Steve Block check_spacing(file_extension, clean_lines, line_number, error) 2495d0825bca7fe65beaee391d30da42e937db621564Steve Block check_check(clean_lines, line_number, error) 2496d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_comparisons_to_zero(clean_lines, line_number, error) 2497f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch check_for_null(clean_lines, line_number, file_state, error) 24980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 24990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') 25010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') 25020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches the first component of a filename delimited by -s and _s. That is: 25030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' 25040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' 25050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' 25060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' 25070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') 25080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef _drop_common_suffixes(filename): 25110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Drops common suffixes like _test.cpp or -inl.h from filename. 25120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example: 25140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo-inl.h') 25150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo' 25160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/bar/foo.cpp') 25170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/bar/foo' 25180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo_internal.h') 25190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo' 25200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo_unusualinternal.h') 25210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo_unusualinternal' 25220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 25240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The input filename. 25250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 25270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The filename with the common suffix removed. 25280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 25290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for suffix in ('test.cpp', 'regtest.cpp', 'unittest.cpp', 25300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'inl.h', 'impl.h', 'internal.h'): 25310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (filename.endswith(suffix) and len(filename) > len(suffix) 25320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and filename[-len(suffix) - 1] in ('-', '_')): 25330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return filename[:-len(suffix) - 1] 25340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return os.path.splitext(filename)[0] 25350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef _classify_include(filename, include, is_system, include_state): 25380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Figures out what kind of header 'include' is. 25390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 25410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The current file cpp_style is running over. 25420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include: The path to a #included file. 25430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_system: True if the #include used <> rather than "". 25440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 25450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 25470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch One of the _XXX_HEADER constants. 25480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example: 25500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'config.h', False) 25510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_HEADER 25520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'foo.h', False) 25530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_HEADER 25540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'bar.h', False) 25550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_HEADER 25560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 25570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If it is a system header we know it is classified as _OTHER_HEADER. 25590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if is_system: 25600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER 25610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the include is named config.h then this is WebCore/config.h. 25630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if include == "config.h": 25640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _CONFIG_HEADER 25650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There cannot be primary includes in header files themselves. Only an 25670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include exactly matches the header filename will be is flagged as 25680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # primary, so that it triggers the "don't include yourself" check. 25690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename.endswith('.h') and filename != include: 25700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER; 25710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2572d0825bca7fe65beaee391d30da42e937db621564Steve Block # Qt's moc files do not follow the naming and ordering rules, so they should be skipped 2573d0825bca7fe65beaee391d30da42e937db621564Steve Block if include.startswith('moc_') and include.endswith('.cpp'): 2574d0825bca7fe65beaee391d30da42e937db621564Steve Block return _MOC_HEADER 2575d0825bca7fe65beaee391d30da42e937db621564Steve Block 2576d0825bca7fe65beaee391d30da42e937db621564Steve Block if include.endswith('.moc'): 2577d0825bca7fe65beaee391d30da42e937db621564Steve Block return _MOC_HEADER 2578d0825bca7fe65beaee391d30da42e937db621564Steve Block 25790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the target file basename starts with the include we're checking 25800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # then we consider it the primary header. 25810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch target_base = FileInfo(filename).base_name() 25820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_base = FileInfo(include).base_name() 25830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we haven't encountered a primary header, then be lenient in checking. 2585643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not include_state.visited_primary_section() and target_base.find(include_base) != -1: 25860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _PRIMARY_HEADER 25870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we already encountered a primary header, perform a strict comparison. 25880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In case the two filename bases are the same then the above lenient check 25890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # probably was a false positive. 25900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif include_state.visited_primary_section() and target_base == include_base: 2591d0825bca7fe65beaee391d30da42e937db621564Steve Block if include == "ResourceHandleWin.h": 2592d0825bca7fe65beaee391d30da42e937db621564Steve Block # FIXME: Thus far, we've only seen one example of these, but if we 2593d0825bca7fe65beaee391d30da42e937db621564Steve Block # start to see more, please consider generalizing this check 2594d0825bca7fe65beaee391d30da42e937db621564Steve Block # somehow. 2595d0825bca7fe65beaee391d30da42e937db621564Steve Block return _OTHER_HEADER 25960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _PRIMARY_HEADER 25970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER 25990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochdef _does_primary_header_exist(filename): 26022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """Return a primary header file name for a file, or empty string 26032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if the file is not source file or primary header does not exist. 26042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch """ 26052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fileinfo = FileInfo(filename) 26062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if not fileinfo.is_source(): 26072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return False 26082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch primary_header = fileinfo.no_extension() + ".h" 26092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return os.path.isfile(primary_header) 26102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 26112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2612d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_include_line(filename, file_extension, clean_lines, line_number, include_state, error): 26130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Check rules that are applicable to #include lines. 26140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Strings on #include lines are NOT removed from elided line, to make 26160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch certain tasks easier. However, to prevent false positives, checks 26170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch applicable to #include lines in CheckLanguage must be put here. 26180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 26200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 2621d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The current file extension, without the leading dot. 26220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 26230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 26240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 26250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 26260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 26278a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # FIXME: For readability or as a possible optimization, consider 26288a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # exiting early here by checking whether the "build/include" 26298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # category should be checked for the given filename. This 26308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # may involve having the error handler classes expose a 26318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # should_check() method, in addition to the usual __call__ 26328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # method. 26330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.lines[line_number] 26340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(line) 26360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 26370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 26380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include = matched.group(2) 26400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_system = (matched.group(1) == '<') 26410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for any of the stream classes that are part of standard C++. 26430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): 26448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block error(line_number, 'readability/streams', 3, 26458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 'Streams are highly discouraged.') 26460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for specific includes to fix. 26480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if include.startswith('wtf/') and not is_system: 2649d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include', 4, 26500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'wtf includes should be <wtf/file.h> instead of "wtf/file.h".') 26510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch duplicate_header = include in include_state 26530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if duplicate_header: 2654d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include', 4, 26550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '"%s" already included at %s:%s' % 26560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (include, filename, include_state[include])) 26570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 26580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state[include] = line_number 26590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_type = _classify_include(filename, include, is_system, include_state) 26612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch primary_header_exists = _does_primary_header_exist(filename) 26620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state.header_types[line_number] = header_type 26630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only proceed if this isn't a duplicate header. 26650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if duplicate_header: 26660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 26670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We want to ensure that headers appear in the right order: 26690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 1) for implementation files: config.h, primary header, blank line, alphabetically sorted 26700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 2) for header files: alphabetically sorted 26710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The include_state object keeps track of the last type seen 26720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # and complains if the header types are out of order or missing. 26732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch error_message = include_state.check_next_include_order(header_type, 26742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch file_extension == "h", 26752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch primary_header_exists) 26760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to make sure we have a blank line after primary header. 26780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not error_message and header_type == _PRIMARY_HEADER: 26790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch next_line = clean_lines.raw_lines[line_number + 1] 26800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_blank_line(next_line): 2681d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 26820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You should add a blank line after implementation file\'s own header.') 26830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to make sure all headers besides config.h and the primary header are 2685d0825bca7fe65beaee391d30da42e937db621564Steve Block # alphabetically sorted. Skip Qt's moc files. 26860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not error_message and header_type == _OTHER_HEADER: 26870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number - 1; 26880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.lines[previous_line_number] 26890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_match = _RE_PATTERN_INCLUDE.search(previous_line) 26900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (not previous_match and previous_line_number > 0 26910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', previous_line)): 26920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number -= 1; 26930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.lines[previous_line_number] 26940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_match = _RE_PATTERN_INCLUDE.search(previous_line) 26950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if previous_match: 26960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_header_type = include_state.header_types[previous_line_number] 26970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if previous_header_type == _OTHER_HEADER and previous_line.strip() > line.strip(): 2698d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 26990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Alphabetical sorting problem.') 27000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if error_message: 2702d0825bca7fe65beaee391d30da42e937db621564Steve Block if file_extension == 'h': 2703d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 27040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%s Should be: alphabetically sorted.' % 27050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message) 27060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 2707d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 27080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%s Should be: config.h, primary header, blank line, and then alphabetically sorted.' % 27090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message) 27100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef check_language(filename, clean_lines, line_number, file_extension, include_state, 2713f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state, error): 27140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks rules from the 'C++ language rules' section of cppguide.html. 27150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Some of these rules are hard to test (function overloading, using 27170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch uint32 inappropriately), but we do the best we can. 27180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 27200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 27210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 27220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 27230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (without the dot) of the filename. 27240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 2725f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state: A _FileState instance which maintains information about 2726f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch the state of things in the file. 27270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 27280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 27290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the line is empty or consists of entirely a comment, no need to 27300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # check it. 27310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 27320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not line: 27330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 27340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(line) 27360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2737d0825bca7fe65beaee391d30da42e937db621564Steve Block check_include_line(filename, file_extension, clean_lines, line_number, include_state, error) 27380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 27390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: figure out if they're using default arguments in fn proto. 27410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to see if they're using an conversion function cast. 27430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # I just try to capture the most common basic types, though there are more. 27440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Parameterless conversion functions, such as bool(), are allowed as they are 27450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # probably a member operator declaration or default constructor. 27460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search( 27470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) 27480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 27490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # gMock methods are defined using some variant of MOCK_METHODx(name, type) 27500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # where type may be float(), int(string), etc. Without context they are 27510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # virtually indistinguishable from int(x) casts. 27520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line): 2753d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/casting', 4, 27540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using deprecated casting style. ' 27550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Use static_cast<%s>(...) instead' % 27560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(1)) 27570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2758d0825bca7fe65beaee391d30da42e937db621564Steve Block check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number], 27590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'static_cast', 27600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\((int|float|double|bool|char|u?int(16|32|64))\)', 27610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error) 27620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This doesn't catch all cases. Consider (const char * const)"hello". 2763d0825bca7fe65beaee391d30da42e937db621564Steve Block check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number], 27640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) 27650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In addition, we look for people taking the address of a cast. This 27670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # is dangerous -- casts can assign to temporaries, so the pointer doesn't 27680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # point where you think. 27690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search( 27700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): 2771d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/casting', 4, 27720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('Are you taking an address of a cast? ' 27730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'This is dangerous: could be a temp var. ' 27740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Take the address before doing the cast, rather than after')) 27750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for people declaring static/global STL strings at the top level. 27770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This is dangerous because the C++ language does not guarantee that 27780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # globals with constructors are initialized before the first access. 27790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = match( 27800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', 27810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line) 27820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Make sure it's not a function. 27830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Function template specialization looks like: "string foo<Type>(...". 27840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Class template definitions look like: "string Foo<Type>::Method(...". 27850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched and not match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', 27860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(3)): 2787d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/string', 4, 27880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'For a static/global string constant, use a C style string instead: ' 27890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '"%schar %s[]".' % 27900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (matched.group(1), matched.group(2))) 27910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check that we're not using RTTI outside of testing code. 27938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if search(r'\bdynamic_cast<', line): 2794d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/rtti', 5, 27950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use dynamic_cast<>. If you need to cast within a class ' 27960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "hierarchy, use static_cast<> to upcast. Google doesn't support " 27970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'RTTI.') 27980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): 2800d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/init', 4, 28010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You seem to be initializing a member variable with itself.') 28020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if file_extension == 'h': 28040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: check that 1-arg constructors are explicit. 28050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # How to tell it's a constructor? 28060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # (handled in check_for_non_standard_constructs for now) 28070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pass 28080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if people are using the verboten C basic types. The only exception 28100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # we regularly allow is "unsigned short port" for port. 28110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bshort port\b', line): 28120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'\bunsigned short port\b', line): 2813d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/int', 4, 28140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Use "unsigned short" for ports, not "short"') 28150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # When snprintf is used, the second argument shouldn't be a literal. 28170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) 28180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2819d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 3, 28200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 28210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'to snprintf.' % (matched.group(1), matched.group(2))) 28220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if some verboten C functions are being used. 28240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bsprintf\b', line): 2825d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 5, 28260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Never use sprintf. Use snprintf instead.') 28270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'\b(strcpy|strcat)\b', line) 28280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2829d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 4, 28300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Almost always, snprintf is better than %s' % matched.group(1)) 28310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bsscanf\b', line): 2833d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 1, 28340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'sscanf can be ok, but is slow and can overflow buffers.') 28350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for suspicious usage of "if" like 28370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } if (a == b) { 28380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\}\s*if\s*\(', line): 2839d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/braces', 4, 28400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Did you mean "else if"? If not, start a new line for "if".') 28410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for potential format string bugs like printf(foo). 28430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We constrain the pattern not to pick things like DocidForPrintf(foo). 28440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) 28450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I) 28460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2847d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 4, 28480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Potential format string bug. Do %s("%%s", %s) instead.' 28490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (matched.group(1), matched.group(2))) 28500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for potential memset bugs like memset(buf, sizeof(buf), 0). 28520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) 28530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched and not match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", matched.group(2)): 2854d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/memset', 4, 28550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Did you mean "memset(%s, 0, %s)"?' 28560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (matched.group(1), matched.group(2))) 28570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Detect variable-length arrays. 28590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) 28600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (matched and matched.group(2) != 'return' and matched.group(2) != 'delete' and 28610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(3).find(']') == -1): 28620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Split the size using space and arithmetic operators as delimiters. 28630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If any of the resulting tokens are not compile time constants then 28640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # report the error. 28650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', matched.group(3)) 28660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_const = True 28670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = False 28680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for tok in tokens: 28690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if skip_next: 28700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = False 28710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'sizeof\(.+\)', tok): 28740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'arraysize\(\w+\)', tok): 28760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tok = tok.lstrip('(') 28790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tok = tok.rstrip(')') 28800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not tok: 28810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\d+', tok): 28830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'0[xX][0-9a-fA-F]+', tok): 28850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'k[A-Z0-9]\w*', tok): 28870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(.+::)?k[A-Z0-9]\w*', tok): 28890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): 28910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # A catch all for tricky sizeof cases, including 'sizeof expression', 28930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' 28940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # requires skipping the next token becasue we split on ' ' and '*'. 28950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if tok.startswith('sizeof'): 28960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = True 28970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 28980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_const = False 28990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 29000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_const: 2901d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/arrays', 1, 29020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use variable-length arrays. Use an appropriately named ' 29030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "('k' followed by CamelCase) compile-time constant for the size.") 29040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 29050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for use of unnamed namespaces in header files. Registration 29060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # macros are typically OK, so we allow use of "namespace {" on lines 29070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that end with backslashes. 29080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (file_extension == 'h' 29090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and search(r'\bnamespace\s*{', line) 29100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line[-1] != '\\'): 2911d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/namespaces', 4, 29120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use unnamed namespaces in header files. See ' 29130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 29140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' for more information.') 29150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2916f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch check_identifier_name_in_declaration(filename, line_number, line, file_state, error) 2917643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2918643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2919f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef check_identifier_name_in_declaration(filename, line_number, line, file_state, error): 2920643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Checks if identifier names contain any underscores. 2921643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2922643ca7872b450ea4efacab6188849e5aac2ba161Steve Block As identifiers in libraries we are using have a bunch of 2923643ca7872b450ea4efacab6188849e5aac2ba161Steve Block underscores, we only warn about the declarations of identifiers 2924643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and don't check use of identifiers. 2925643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2926643ca7872b450ea4efacab6188849e5aac2ba161Steve Block Args: 2927643ca7872b450ea4efacab6188849e5aac2ba161Steve Block filename: The name of the current file. 2928643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line_number: The number of the line to check. 2929643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line: The line of code to check. 2930f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state: A _FileState instance which maintains information about 2931f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch the state of things in the file. 2932643ca7872b450ea4efacab6188849e5aac2ba161Steve Block error: The function to call with any errors found. 2933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """ 2934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We don't check a return statement. 2935d0825bca7fe65beaee391d30da42e937db621564Steve Block if match(r'\s*(return|delete)\b', line): 2936643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2937643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2938643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Basically, a declaration is a type name followed by whitespaces 2939643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # followed by an identifier. The type name can be complicated 2940643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # due to type adjectives and templates. We remove them first to 2941643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # simplify the process to find declarations of identifiers. 2942643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2943643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Convert "long long", "long double", and "long long int" to 2944643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # simple types, but don't remove simple "long". 2945643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'long (long )?(?=long|double|int)', '', line) 2946692e5dbf12901edacf14812a6fae25462920af42Steve Block # Convert unsigned/signed types to simple types, too. 2947692e5dbf12901edacf14812a6fae25462920af42Steve Block line = sub(r'(unsigned|signed) (?=char|short|int|long)', '', line) 2948692e5dbf12901edacf14812a6fae25462920af42Steve Block line = sub(r'\b(inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line) 2949643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2950dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch # Remove "new" and "new (expr)" to simplify, too. 2951dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch line = sub(r'new\s*(\([^)]*\))?', '', line) 2952dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch 2953643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Remove all template parameters by removing matching < and >. 2954643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Loop until no templates are removed to remove nested templates. 2955643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while True: 2956643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line, number_of_replacements = subn(r'<([\w\s:]|::)+\s*[*&]*\s*>', '', line) 2957643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not number_of_replacements: 2958643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break 2959643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2960643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Declarations of local variables can be in condition expressions 2961643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # of control flow statements (e.g., "if (RenderObject* p = o->parent())"). 2962643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We remove the keywords and the first parenthesis. 2963643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2964643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Declarations in "while", "if", and "switch" are different from 2965643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # other declarations in two aspects: 2966643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2967643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # - There can be only one declaration between the parentheses. 2968643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # (i.e., you cannot write "if (int i = 0, j = 1) {}") 2969643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # - The variable must be initialized. 2970643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # (i.e., you cannot write "if (int i) {}") 2971643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2972643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # and we will need different treatments for them. 2973643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'^\s*for\s*\(', '', line) 2974643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line, control_statement = subn(r'^\s*(while|else if|if|switch)\s*\(', '', line) 2975643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2976643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Detect variable and functions. 2977643ca7872b450ea4efacab6188849e5aac2ba161Steve Block type_regexp = r'\w([\w]|\s*[*&]\s*|::)+' 2978643ca7872b450ea4efacab6188849e5aac2ba161Steve Block identifier_regexp = r'(?P<identifier>[\w:]+)' 2979692e5dbf12901edacf14812a6fae25462920af42Steve Block maybe_bitfield_regexp = r'(:\s*\d+\s*)?' 2980643ca7872b450ea4efacab6188849e5aac2ba161Steve Block character_after_identifier_regexp = r'(?P<character_after_identifier>[[;()=,])(?!=)' 2981692e5dbf12901edacf14812a6fae25462920af42Steve Block declaration_without_type_regexp = r'\s*' + identifier_regexp + r'\s*' + maybe_bitfield_regexp + character_after_identifier_regexp 2982643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_with_type_regexp = r'\s*' + type_regexp + r'\s' + declaration_without_type_regexp 2983643ca7872b450ea4efacab6188849e5aac2ba161Steve Block is_function_arguments = False 2984643ca7872b450ea4efacab6188849e5aac2ba161Steve Block number_of_identifiers = 0 2985643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while True: 2986643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # If we are seeing the first identifier or arguments of a 2987643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # function, there should be a type name before an identifier. 2988643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not number_of_identifiers or is_function_arguments: 2989643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_regexp = declaration_with_type_regexp 2990643ca7872b450ea4efacab6188849e5aac2ba161Steve Block else: 2991643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_regexp = declaration_without_type_regexp 2992643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2993643ca7872b450ea4efacab6188849e5aac2ba161Steve Block matched = match(declaration_regexp, line) 2994643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not matched: 2995643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2996643ca7872b450ea4efacab6188849e5aac2ba161Steve Block identifier = matched.group('identifier') 2997643ca7872b450ea4efacab6188849e5aac2ba161Steve Block character_after_identifier = matched.group('character_after_identifier') 2998643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2999643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # If we removed a non-for-control statement, the character after 3000643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # the identifier should be '='. With this rule, we can avoid 3001643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # warning for cases like "if (val & INT_MAX) {". 3002643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if control_statement and character_after_identifier != '=': 3003643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 3004643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3005643ca7872b450ea4efacab6188849e5aac2ba161Steve Block is_function_arguments = is_function_arguments or character_after_identifier == '(' 3006643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3007643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Remove "m_" and "s_" to allow them. 3008643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modified_identifier = sub(r'(^|(?<=::))[ms]_', '', identifier) 3009f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not file_state.is_objective_c() and modified_identifier.find('_') >= 0: 3010643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Various exceptions to the rule: JavaScript op codes functions, const_iterator. 3011a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (not (filename.find('JavaScriptCore') >= 0 and modified_identifier.find('op_') >= 0) 3012d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('tst_') 3013d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('webkit_dom_object_') 3014db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block and not modified_identifier.startswith('NPN_') 3015db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block and not modified_identifier.startswith('NPP_') 3016db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block and not modified_identifier.startswith('NP_') 3017d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('qt_') 301868513a70bcd92384395513322f1b801e7bf9c729Steve Block and not modified_identifier.startswith('cairo_') 3019d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.find('::qt_') >= 0 3020a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch and not modified_identifier == "const_iterator" 3021a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch and not modified_identifier == "vm_throw"): 3022d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.") 3023643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 302421939df44de1705786c545cd1bf519d47250322dBen Murdoch # Check for variables named 'l', these are too easy to confuse with '1' in some fonts 302521939df44de1705786c545cd1bf519d47250322dBen Murdoch if modified_identifier == 'l': 302621939df44de1705786c545cd1bf519d47250322dBen Murdoch error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use the single letter 'l' as an identifier name.") 302721939df44de1705786c545cd1bf519d47250322dBen Murdoch 3028643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # There can be only one declaration in non-for-control statements. 3029643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if control_statement: 3030643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 3031643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We should continue checking if this is a function 3032643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # declaration because we need to check its arguments. 3033643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Also, we need to check multiple declarations. 3034643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if character_after_identifier != '(' and character_after_identifier != ',': 3035643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 3036643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3037643ca7872b450ea4efacab6188849e5aac2ba161Steve Block number_of_identifiers += 1 3038643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = line[matched.end():] 3039643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 3040d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_c_style_cast(line_number, line, raw_line, cast_type, pattern, 30410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error): 30420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for a C-style cast by looking for the pattern. 30430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This also handles sizeof(type) warnings, due to similarity of content. 30450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 30470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 30480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The line of code to check. 30490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_line: The raw line of code to check, with comments. 30500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cast_type: The string for the C++ cast to recommend. This is either 30510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reinterpret_cast or static_cast, depending. 30520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pattern: The regular expression used to find C-style casts. 30530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 30540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 30550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(pattern, line) 30560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 30570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 30580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # e.g., sizeof(int) 30600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch sizeof_match = match(r'.*sizeof\s*$', line[0:matched.start(1) - 1]) 30610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if sizeof_match: 3062d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/sizeof', 1, 30630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using sizeof(type). Use sizeof(varname) instead if possible') 30640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 30650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remainder = line[matched.end(0):] 30670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The close paren is for function pointers as arguments to a function. 30690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void foo(void (*bar)(int)); 30700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The semicolon check is a more basic function check; also possibly a 30710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function pointer typedef. 30720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void foo(int); or void foo(int) const; 30730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The equals check is for function pointer assignment. 30740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void *(*foo)(int) = ... 30750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 30760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Right now, this will only catch cases where there's a single argument, and 30770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # it's unnamed. It should probably be expanded to check for multiple 30780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # arguments with some unnamed. 30790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_match = match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder) 30800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if function_match: 30810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (not function_match.group(3) 30820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or function_match.group(3) == ';' 30830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or raw_line.find('/*') < 0): 3084d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/function', 3, 30850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'All parameters should be named in a function') 30860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 30870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # At this point, all that should be left is actual casts. 3089d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/casting', 4, 30900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using C-style cast. Use %s<%s>(...) instead' % 30910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (cast_type, matched.group(1))) 30920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 30940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_HEADERS_CONTAINING_TEMPLATES = ( 30950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<deque>', ('deque',)), 30960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<functional>', ('unary_function', 'binary_function', 30970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'plus', 'minus', 'multiplies', 'divides', 'modulus', 30980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'negate', 30990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'equal_to', 'not_equal_to', 'greater', 'less', 31000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'greater_equal', 'less_equal', 31010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'logical_and', 'logical_or', 'logical_not', 31020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'unary_negate', 'not1', 'binary_negate', 'not2', 31030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'bind1st', 'bind2nd', 31040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pointer_to_unary_function', 31050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pointer_to_binary_function', 31060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ptr_fun', 31070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', 31080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_ref_t', 31090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'const_mem_fun_t', 'const_mem_fun1_t', 31100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', 31110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_ref', 31120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch )), 31130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<limits>', ('numeric_limits',)), 31140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<list>', ('list',)), 31150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<map>', ('map', 'multimap',)), 31160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<memory>', ('allocator',)), 31170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<queue>', ('queue', 'priority_queue',)), 31180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<set>', ('set', 'multiset',)), 31190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<stack>', ('stack',)), 31200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<string>', ('char_traits', 'basic_string',)), 31210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<utility>', ('pair',)), 31220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<vector>', ('vector',)), 31230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # gcc extensions. 31250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note: std::hash is their hash, ::hash is our hash 31260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<hash_map>', ('hash_map', 'hash_multimap',)), 31270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<hash_set>', ('hash_set', 'hash_multiset',)), 31280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<slist>', ('slist',)), 31290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ) 31300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { 31320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We can trust with reasonable confidence that map gives us pair<>, too. 31330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') 31340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 31350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_STRING = re.compile(r'\bstring\b') 31370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_re_pattern_algorithm_header = [] 31390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', 31400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'transform'): 31410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or 31420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # type::max(). 31430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _re_pattern_algorithm_header.append( 31440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), 31450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _template, 31460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '<algorithm>')) 31470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_re_pattern_templates = [] 31490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor _header, _templates in _HEADERS_CONTAINING_TEMPLATES: 31500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for _template in _templates: 31510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _re_pattern_templates.append( 31520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (re.compile(r'(\<|\b)' + _template + r'\s*\<'), 31530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _template + '<>', 31540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _header)) 31550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef files_belong_to_same_module(filename_cpp, filename_h): 31580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Check if these two filenames belong to the same module. 31590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The concept of a 'module' here is a as follows: 31610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch foo.h, foo-inl.h, foo.cpp, foo_test.cpp and foo_unittest.cpp belong to the 31620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch same 'module' if they are in the same directory. 31630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch some/path/public/xyzzy and some/path/internal/xyzzy are also considered 31640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch to belong to the same module here. 31650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch If the filename_cpp contains a longer path than the filename_h, for example, 31670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '/absolute/path/to/base/sysinfo.cpp', and this file would include 31680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'base/sysinfo.h', this function also produces the prefix needed to open the 31690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header. This is used by the caller of this function to more robustly open the 31700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header file. We don't have access to the real include paths in this context, 31710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch so we need this guesswork here. 31720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Known bugs: tools/base/bar.cpp and base/bar.h belong to the same module 31740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch according to this implementation. Because of this, this function gives 31750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch some false positives. This should be sufficiently rare in practice. 31760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 31780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp: is the path for the .cpp file 31790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h: is the path for the header path 31800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 31820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Tuple with a bool and a string: 31830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch bool: True if filename_cpp and filename_h belong to the same module. 31840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch string: the additional prefix needed to open the header file. 31850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 31860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not filename_cpp.endswith('.cpp'): 31880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (False, '') 31890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('.cpp')] 31900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename_cpp.endswith('_unittest'): 31910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('_unittest')] 31920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif filename_cpp.endswith('_test'): 31930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('_test')] 31940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp.replace('/public/', '/') 31950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp.replace('/internal/', '/') 31960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 31970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not filename_h.endswith('.h'): 31980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (False, '') 31990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h[:-len('.h')] 32000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename_h.endswith('-inl'): 32010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h[:-len('-inl')] 32020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h.replace('/public/', '/') 32030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h.replace('/internal/', '/') 32040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch files_belong_to_same_module = filename_cpp.endswith(filename_h) 32060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch common_path = '' 32070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if files_belong_to_same_module: 32080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch common_path = filename_cpp[:-len(filename_h)] 32090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return files_belong_to_same_module, common_path 32100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef update_include_state(filename, include_state, io=codecs): 32130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Fill up the include_state with new includes found from the file. 32140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 32160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: the name of the header to read. 32170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: an _IncludeState instance in which the headers are inserted. 32180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch io: The io factory to use to read the file. Provided for testability. 32190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 32210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True if a header was succesfully added. False otherwise. 32220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 3223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch io = _unit_test_config.get(INCLUDE_IO_INJECTION_KEY, codecs) 32240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_file = None 32250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch try: 32260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_file = io.open(filename, 'r', 'utf8', 'replace') 32270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch except IOError: 32280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return False 32290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number = 0 32300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in header_file: 32310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number += 1 32320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_line = cleanse_comments(line) 32330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(clean_line) 32340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 32350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include = matched.group(2) 32360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The value formatting is cute, but not really used right now. 32370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # What matters here is that the key is in include_state. 32380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state.setdefault(include, '%s:%d' % (filename, line_number)) 32390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return True 32400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef check_for_include_what_you_use(filename, clean_lines, include_state, error): 32430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Reports for missing stl includes. 32440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function will output warnings to make sure you are including the headers 32460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch necessary for the stl containers and functions that you use. We only give one 32470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reason to include a header. For example, if you use both equal_to<> and 32480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch less<> in a .h file, only one (the latter in the file) of these will be 32490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reported as a reason to include the <functional>. 32500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 32520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 32530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 32540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance. 32550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 32560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 32570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required = {} # A map of header name to line_number and the template entity. 32580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Example of required: { '<functional>': (1219, 'less<>') } 32590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number in xrange(clean_lines.num_lines()): 32610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 32620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not line or line[0] == '#': 32630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 32640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # String is special -- it is a non-templatized type in STL. 32660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if _RE_PATTERN_STRING.search(line): 32670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required['<string>'] = (line_number, 'string') 32680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern, template, header in _re_pattern_algorithm_header: 32700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if pattern.search(line): 32710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required[header] = (line_number, template) 32720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The following function is just a speed up, no semantics are changed. 32740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not '<' in line: # Reduces the cpu time usage by skipping lines. 32750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 32760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern, template, header in _re_pattern_templates: 32780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if pattern.search(line): 32790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required[header] = (line_number, template) 32800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The policy is that if you #include something in foo.h you don't need to 32820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include it again in foo.cpp. Here, we will look at possible includes. 32830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Let's copy the include_state so it is only messed up within this function. 32840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state = include_state.copy() 32850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Did we find the header for this file (if any) and succesfully load it? 32870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_found = False 32880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Use the absolute path so that matching works properly. 32900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch abs_filename = os.path.abspath(filename) 32910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 32920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For Emacs's flymake. 32930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If cpp_style is invoked from Emacs's flymake, a temporary file is generated 32940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # by flymake and that file name might end with '_flymake.cpp'. In that case, 32950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # restore original file name here so that the corresponding header file can be 32960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # found. 32970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # e.g. If the file name is 'foo_flymake.cpp', we should search for 'foo.h' 32980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # instead of 'foo_flymake.h' 3299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block abs_filename = re.sub(r'_flymake\.cpp$', '.cpp', abs_filename) 33000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include_state is modified during iteration, so we iterate over a copy of 33020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the keys. 33030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for header in include_state.keys(): #NOLINT 33040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (same_module, common_path) = files_belong_to_same_module(abs_filename, header) 33050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch fullpath = common_path + header 3306f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if same_module and update_include_state(fullpath, include_state): 33070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_found = True 33080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we can't find the header file for a .cpp, assume it's because we don't 33100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # know where to look. In that case we'll give up as we're not sure they 33110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # didn't include it in the .h file. 33120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: Do a better job of finding .h files so we are confident that 33130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # not having the .h file means there isn't one. 33140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename.endswith('.cpp') and not header_found: 33150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 33160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # All the lines have been processed, report the errors found. 33180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for required_header_unstripped in required: 33190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch template = required[required_header_unstripped][1] 33200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED: 33210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template] 33220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if [True for header in headers if header in include_state]: 33230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 33240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if required_header_unstripped.strip('<>"') not in include_state: 3325d0825bca7fe65beaee391d30da42e937db621564Steve Block error(required[required_header_unstripped][0], 33260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'build/include_what_you_use', 4, 33270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Add #include ' + required_header_unstripped + ' for ' + template) 33280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef process_line(filename, file_extension, 33310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines, line, include_state, function_state, 3332643ca7872b450ea4efacab6188849e5aac2ba161Steve Block class_state, file_state, error): 33330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Processes a single line in the file. 33340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 33360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: Filename of the file that is being processed. 33370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 33380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: An array of strings, each representing a line of the file, 33390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch with comments stripped. 33400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: Number of line being processed. 33410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 33420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state: A _FunctionState instance which counts function lines, etc. 33430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state: A _ClassState instance which maintains information about 33440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the current stack of nested class declarations being parsed. 3345643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 3346643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 3347d0825bca7fe65beaee391d30da42e937db621564Steve Block error: A callable to which errors are reported, which takes arguments: 3348d0825bca7fe65beaee391d30da42e937db621564Steve Block line number, error level, and message 33490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 33510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 33526b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner detect_functions(clean_lines, line, function_state, error) 3353d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_function_lengths(clean_lines, line, function_state, error) 33540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines 33550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 335681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch check_function_definition(filename, file_extension, clean_lines, line, function_state, error) 33576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner check_pass_ptr_usage(clean_lines, line, function_state, error) 3358d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_multiline_comments_and_strings(clean_lines, line, error) 33590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen check_style(clean_lines, line, file_extension, class_state, file_state, error) 33600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_language(filename, clean_lines, line, file_extension, include_state, 3361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state, error) 3362d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_non_standard_constructs(clean_lines, line, class_state, error) 3363d0825bca7fe65beaee391d30da42e937db621564Steve Block check_posix_threading(clean_lines, line, error) 3364d0825bca7fe65beaee391d30da42e937db621564Steve Block check_invalid_increment(clean_lines, line, error) 33650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3367dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdef _process_lines(filename, file_extension, lines, error, min_confidence): 33680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Performs lint checks and reports any errors to the given error function. 33690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 33710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: Filename of the file that is being processed. 33720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 33730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file, with the 33740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch last element being empty if the file is termined with a newline. 33750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: A callable to which errors are reported, which takes 4 arguments: 33760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 33770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines = (['// marker so line numbers and indices both start at 1'] + lines + 33780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ['// marker so line numbers end in a known way']) 33790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state = _IncludeState() 3381dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block function_state = _FunctionState(min_confidence) 33820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state = _ClassState() 33830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3384d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_copyright(lines, error) 33850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if file_extension == 'h': 33870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_for_header_guard(filename, lines, error) 33880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3389d0825bca7fe65beaee391d30da42e937db621564Steve Block remove_multi_line_comments(lines, error) 33900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines = CleansedLines(lines) 3391f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch file_state = _FileState(clean_lines, file_extension) 33920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in xrange(clean_lines.num_lines()): 33930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch process_line(filename, file_extension, clean_lines, line, 3394643ca7872b450ea4efacab6188849e5aac2ba161Steve Block include_state, function_state, class_state, file_state, error) 3395d0825bca7fe65beaee391d30da42e937db621564Steve Block class_state.check_finished(error) 33960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_for_include_what_you_use(filename, clean_lines, include_state, error) 33980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 33990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We check here rather than inside process_line so that we see raw 34000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # lines rather than "cleaned" lines. 3401d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_unicode_replacement_characters(lines, error) 34020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3403d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_new_line_at_eof(lines, error) 34040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 34050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 340621939df44de1705786c545cd1bf519d47250322dBen Murdochclass CppChecker(object): 34070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3408d0825bca7fe65beaee391d30da42e937db621564Steve Block """Processes C++ lines for checking style.""" 34090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3410d0825bca7fe65beaee391d30da42e937db621564Steve Block # This list is used to-- 3411d0825bca7fe65beaee391d30da42e937db621564Steve Block # 3412d0825bca7fe65beaee391d30da42e937db621564Steve Block # (1) generate an explicit list of all possible categories, 3413d0825bca7fe65beaee391d30da42e937db621564Steve Block # (2) unit test that all checked categories have valid names, and 3414d0825bca7fe65beaee391d30da42e937db621564Steve Block # (3) unit test that all categories are getting unit tested. 3415d0825bca7fe65beaee391d30da42e937db621564Steve Block # 3416d0825bca7fe65beaee391d30da42e937db621564Steve Block categories = set([ 3417d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/class', 3418d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/deprecated', 3419d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/endif_comment', 3420d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/forward_decl', 3421d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/header_guard', 3422d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include', 3423d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include_order', 3424d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include_what_you_use', 3425d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/namespaces', 3426d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/printf_format', 3427d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/storage_class', 3428d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/using_std', 3429d0825bca7fe65beaee391d30da42e937db621564Steve Block 'legal/copyright', 3430d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/braces', 3431d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/casting', 3432d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/check', 3433d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/comparison_to_zero', 3434d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/constructors', 3435d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/control_flow', 3436d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/fn_size', 3437d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/function', 3438d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/multiline_comment', 3439d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/multiline_string', 3440cad810f21b803229eb11403f9209855525a25d57Steve Block 'readability/parameter_name', 3441d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/naming', 3442d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/null', 34436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 'readability/pass_ptr', 3444d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/streams', 3445d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/todo', 3446d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/utf8', 344781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 'readability/webkit_api', 3448d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/arrays', 3449d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/casting', 3450d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/explicit', 3451d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/init', 3452d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/int', 3453d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/invalid_increment', 3454d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/max_min_macros', 3455d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/memset', 3456d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/printf', 3457d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/printf_format', 3458d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/references', 3459d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/rtti', 3460d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/sizeof', 3461d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/string', 3462d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/threadsafe_fn', 3463d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/virtual', 3464d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/blank_line', 3465d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/braces', 3466d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/comma', 3467d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/comments', 3468d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/declaration', 3469d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/end_of_line', 3470d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/ending_newline', 3471d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/indent', 3472d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/labels', 3473d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/line_length', 3474d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/newline', 3475d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/operators', 3476d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/parens', 3477d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/semicolon', 3478d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/tab', 3479d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/todo', 3480d0825bca7fe65beaee391d30da42e937db621564Steve Block ]) 3481d0825bca7fe65beaee391d30da42e937db621564Steve Block 3482dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block def __init__(self, file_path, file_extension, handle_style_error, 3483dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block min_confidence): 348421939df44de1705786c545cd1bf519d47250322dBen Murdoch """Create a CppChecker instance. 34850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3486d0825bca7fe65beaee391d30da42e937db621564Steve Block Args: 3487d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: A string that is the file extension, without 3488d0825bca7fe65beaee391d30da42e937db621564Steve Block the leading dot. 34890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3490d0825bca7fe65beaee391d30da42e937db621564Steve Block """ 3491d0825bca7fe65beaee391d30da42e937db621564Steve Block self.file_extension = file_extension 3492d0825bca7fe65beaee391d30da42e937db621564Steve Block self.file_path = file_path 3493d0825bca7fe65beaee391d30da42e937db621564Steve Block self.handle_style_error = handle_style_error 3494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block self.min_confidence = min_confidence 3495d0825bca7fe65beaee391d30da42e937db621564Steve Block 3496d0825bca7fe65beaee391d30da42e937db621564Steve Block # Useful for unit testing. 3497d0825bca7fe65beaee391d30da42e937db621564Steve Block def __eq__(self, other): 349821939df44de1705786c545cd1bf519d47250322dBen Murdoch """Return whether this CppChecker instance is equal to another.""" 3499d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.file_extension != other.file_extension: 3500d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 3501d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.file_path != other.file_path: 3502d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 3503d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.handle_style_error != other.handle_style_error: 3504d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 3505dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if self.min_confidence != other.min_confidence: 3506d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 35070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3508d0825bca7fe65beaee391d30da42e937db621564Steve Block return True 35090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3510d0825bca7fe65beaee391d30da42e937db621564Steve Block # Useful for unit testing. 3511d0825bca7fe65beaee391d30da42e937db621564Steve Block def __ne__(self, other): 3512d0825bca7fe65beaee391d30da42e937db621564Steve Block # Python does not automatically deduce __ne__() from __eq__(). 3513d0825bca7fe65beaee391d30da42e937db621564Steve Block return not self.__eq__(other) 35140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 351521939df44de1705786c545cd1bf519d47250322dBen Murdoch def check(self, lines): 3516d0825bca7fe65beaee391d30da42e937db621564Steve Block _process_lines(self.file_path, self.file_extension, lines, 3517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block self.handle_style_error, self.min_confidence) 35180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 35190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3520d0825bca7fe65beaee391d30da42e937db621564Steve Block# FIXME: Remove this function (requires refactoring unit tests). 3521f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochdef process_file_data(filename, file_extension, lines, error, min_confidence, unit_test_config): 3522f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch global _unit_test_config 3523f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch _unit_test_config = unit_test_config 352421939df44de1705786c545cd1bf519d47250322dBen Murdoch checker = CppChecker(filename, file_extension, error, min_confidence) 352521939df44de1705786c545cd1bf519d47250322dBen Murdoch checker.check(lines) 3526f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch _unit_test_config = {} 3527