10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#!/usr/bin/python 20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# -*- coding: utf-8 -*- 30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# 40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Copyright (C) 2009 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 500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Headers that we consider STL headers. 520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_STL_HEADERS = frozenset([ 530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', 540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', 550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'pair.h', 560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', 580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'utility', 'vector', 'vector.h', 590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ]) 600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Non-STL C++ system headers. 630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CPP_HEADERS = frozenset([ 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', 650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', 660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', 670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', 690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream.h', 710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', 720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'numeric', 'ostream.h', 'parsestream.h', 'pfstream.h', 'PlotFile.h', 730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', 'ropeimpl.h', 740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', 750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', 760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', 770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ]) 780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Assertion macros. These are defined in base/logging.h and 810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# testing/base/gunit.h. Note that the _M versions need to come first 820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# for substring matching to work. 830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CHECK_MACROS = [ 840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'DCHECK', 'CHECK', 850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'EXPECT_TRUE_M', 'EXPECT_TRUE', 860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ASSERT_TRUE_M', 'ASSERT_TRUE', 870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'EXPECT_FALSE_M', 'EXPECT_FALSE', 880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ASSERT_FALSE_M', 'ASSERT_FALSE', 890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ] 900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE 920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) 930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor op, replacement in [('==', 'EQ'), ('!=', 'NE'), 950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('>=', 'GE'), ('>', 'GT'), 960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<=', 'LE'), ('<', 'LT')]: 970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement 980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement 990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement 1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement 1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement 1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement 1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), 1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('>=', 'LT'), ('>', 'LE'), 1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<=', 'GT'), ('<', 'GE')]: 1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement 1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement 1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement 1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement 1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# These constants define types of headers for use with 1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _IncludeState.check_next_include_order(). 1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_CONFIG_HEADER = 0 1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_PRIMARY_HEADER = 1 1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_OTHER_HEADER = 2 118d0825bca7fe65beaee391d30da42e937db621564Steve Block_MOC_HEADER = 3 1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 121643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# The regexp compilation caching is inlined in all regexp functions for 122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# performance reasons; factoring it out into a separate function turns out 123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# to be noticeably expensive. 1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_regexp_compile_cache = {} 1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef match(pattern, s): 1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Matches the string with the pattern, caching the compiled regexp.""" 1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not pattern in _regexp_compile_cache: 1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _regexp_compile_cache[pattern].match(s) 1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef search(pattern, s): 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Searches the string for the pattern, caching the compiled regexp.""" 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not pattern in _regexp_compile_cache: 1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _regexp_compile_cache[pattern].search(s) 1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 141643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdef sub(pattern, replacement, s): 142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Substitutes occurrences of a pattern, caching the compiled regexp.""" 143643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not pattern in _regexp_compile_cache: 144643ca7872b450ea4efacab6188849e5aac2ba161Steve Block _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 145643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return _regexp_compile_cache[pattern].sub(replacement, s) 146643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 147643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 148643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdef subn(pattern, replacement, s): 149643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Substitutes occurrences of a pattern, caching the compiled regexp.""" 150643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not pattern in _regexp_compile_cache: 151643ca7872b450ea4efacab6188849e5aac2ba161Steve Block _regexp_compile_cache[pattern] = sre_compile.compile(pattern) 152643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return _regexp_compile_cache[pattern].subn(replacement, s) 153643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 155d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef up_to_unmatched_closing_paren(s): 156d0825bca7fe65beaee391d30da42e937db621564Steve Block """Splits a string into two parts up to first unmatched ')'. 157d0825bca7fe65beaee391d30da42e937db621564Steve Block 158d0825bca7fe65beaee391d30da42e937db621564Steve Block Args: 159d0825bca7fe65beaee391d30da42e937db621564Steve Block s: a string which is a substring of line after '(' 160d0825bca7fe65beaee391d30da42e937db621564Steve Block (e.g., "a == (b + c))"). 161d0825bca7fe65beaee391d30da42e937db621564Steve Block 162d0825bca7fe65beaee391d30da42e937db621564Steve Block Returns: 163d0825bca7fe65beaee391d30da42e937db621564Steve Block A pair of strings (prefix before first unmatched ')', 164d0825bca7fe65beaee391d30da42e937db621564Steve Block reminder of s after first unmatched ')'), e.g., 165d0825bca7fe65beaee391d30da42e937db621564Steve Block up_to_unmatched_closing_paren("a == (b + c)) { ") 166d0825bca7fe65beaee391d30da42e937db621564Steve Block returns "a == (b + c)", " {". 167d0825bca7fe65beaee391d30da42e937db621564Steve Block Returns None, None if there is no unmatched ')' 168d0825bca7fe65beaee391d30da42e937db621564Steve Block 169d0825bca7fe65beaee391d30da42e937db621564Steve Block """ 170d0825bca7fe65beaee391d30da42e937db621564Steve Block i = 1 171d0825bca7fe65beaee391d30da42e937db621564Steve Block for pos, c in enumerate(s): 172d0825bca7fe65beaee391d30da42e937db621564Steve Block if c == '(': 173d0825bca7fe65beaee391d30da42e937db621564Steve Block i += 1 174d0825bca7fe65beaee391d30da42e937db621564Steve Block elif c == ')': 175d0825bca7fe65beaee391d30da42e937db621564Steve Block i -= 1 176d0825bca7fe65beaee391d30da42e937db621564Steve Block if i == 0: 177d0825bca7fe65beaee391d30da42e937db621564Steve Block return s[:pos], s[pos + 1:] 178d0825bca7fe65beaee391d30da42e937db621564Steve Block return None, None 179d0825bca7fe65beaee391d30da42e937db621564Steve Block 1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _IncludeState(dict): 1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Tracks line numbers for includes, and the order in which includes appear. 1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch As a dict, an _IncludeState object serves as a mapping between include 1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename and line number on which that file was included. 1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Call check_next_include_order() once for each header in the file, passing 1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch in the type constants defined above. Calls in an illegal order will 1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raise an _IncludeError with an appropriate error message. 1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # self._section will move monotonically through this set. If it ever 1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # needs to move backwards, check_next_include_order will raise an error. 1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _INITIAL_SECTION = 0 1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_SECTION = 1 1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_SECTION = 2 1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_SECTION = 3 1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _TYPE_NAMES = { 1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_HEADER: 'WebCore config.h', 2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_HEADER: 'header this file implements', 2010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_HEADER: 'other header', 202d0825bca7fe65beaee391d30da42e937db621564Steve Block _MOC_HEADER: 'moc file', 2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _SECTION_NAMES = { 2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _INITIAL_SECTION: "... nothing.", 2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_SECTION: "WebCore config.h.", 2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_SECTION: 'a header this file implements.', 2080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_SECTION: 'other header.', 2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self): 2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch dict.__init__(self) 2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._INITIAL_SECTION 2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._visited_primary_section = False 2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.header_types = dict(); 2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def visited_primary_section(self): 2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self._visited_primary_section 2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def check_next_include_order(self, header_type, file_is_header): 2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns a non-empty error message if the next header is out of order. 2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function also updates the internal state to be ready to check 2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the next include. 2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_type: One of the _XXX_HEADER constants defined above. 2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_is_header: Whether the file that owns this _IncludeState is itself a header 2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The empty string if the header is in the right order, or an 2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error message describing what's wrong. 2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _CONFIG_HEADER and file_is_header: 2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 'Header file should not contain WebCore config.h.' 2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _PRIMARY_HEADER and file_is_header: 2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 'Header file should not contain itself.' 239d0825bca7fe65beaee391d30da42e937db621564Steve Block if header_type == _MOC_HEADER: 240d0825bca7fe65beaee391d30da42e937db621564Steve Block return '' 2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = '' 2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section != self._OTHER_SECTION: 2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch before_error_message = ('Found %s before %s' % 2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (self._TYPE_NAMES[header_type], 2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._SECTION_NAMES[self._section + 1])) 2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch after_error_message = ('Found %s after %s' % 2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (self._TYPE_NAMES[header_type], 2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._SECTION_NAMES[self._section])) 2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if header_type == _CONFIG_HEADER: 2520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section >= self._CONFIG_SECTION: 2530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = after_error_message 2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._CONFIG_SECTION 2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif header_type == _PRIMARY_HEADER: 2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self._section >= self._PRIMARY_SECTION: 2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = after_error_message 2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif self._section < self._CONFIG_SECTION: 2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = before_error_message 2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._PRIMARY_SECTION 2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._visited_primary_section = True 2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch assert header_type == _OTHER_HEADER 2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not file_is_header and self._section < self._PRIMARY_SECTION: 2650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message = before_error_message 2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._section = self._OTHER_SECTION 2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return error_message 2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 271d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass _FunctionState(object): 272d0825bca7fe65beaee391d30da42e937db621564Steve Block """Tracks current function name and the number of lines in its body. 2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 274d0825bca7fe65beaee391d30da42e937db621564Steve Block Attributes: 275d0825bca7fe65beaee391d30da42e937db621564Steve Block verbosity: The verbosity level to use while checking style. 2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 282d0825bca7fe65beaee391d30da42e937db621564Steve Block def __init__(self, verbosity): 283d0825bca7fe65beaee391d30da42e937db621564Steve Block self.verbosity = verbosity 2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = False 2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines_in_function = 0 2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.current_function = '' 2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def begin(self, function_name): 2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Start analyzing function body. 2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_name: The name of the function being tracked. 2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 2940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = True 2950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines_in_function = 0 2960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.current_function = function_name 2970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def count(self): 2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Count line in current function body.""" 3000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self.in_a_function: 3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines_in_function += 1 3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 303d0825bca7fe65beaee391d30da42e937db621564Steve Block def check(self, error, line_number): 3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Report if too many lines in function body. 3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'T(EST|est)', self.current_function): 3110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_trigger = self._TEST_TRIGGER 3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_trigger = self._NORMAL_TRIGGER 314d0825bca7fe65beaee391d30da42e937db621564Steve Block trigger = base_trigger * 2 ** self.verbosity 3150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self.lines_in_function > trigger: 3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_level = int(math.log(self.lines_in_function / base_trigger, 2)) 3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... 3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if error_level > 5: 3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_level = 5 321d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/fn_size', error_level, 3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Small and focused functions are preferred:' 3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' %s has %d non-comment lines' 3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' (error triggered by exceeding %d lines).' % ( 3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.current_function, self.lines_in_function, trigger)) 3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def end(self): 3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Stop analizing function body.""" 3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.in_a_function = False 3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _IncludeError(Exception): 3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Indicates a problem with the include order in a file.""" 3340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pass 3350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 337d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef is_c_or_objective_c(file_extension): 338d0825bca7fe65beaee391d30da42e937db621564Steve Block """Return whether the file extension corresponds to C or Objective-C. 339d0825bca7fe65beaee391d30da42e937db621564Steve Block 340d0825bca7fe65beaee391d30da42e937db621564Steve Block Args: 341d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The file extension without the leading dot. 342d0825bca7fe65beaee391d30da42e937db621564Steve Block 343d0825bca7fe65beaee391d30da42e937db621564Steve Block """ 344d0825bca7fe65beaee391d30da42e937db621564Steve Block return file_extension in ['c', 'm'] 345d0825bca7fe65beaee391d30da42e937db621564Steve Block 346d0825bca7fe65beaee391d30da42e937db621564Steve Block 3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass FileInfo: 3480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Provides utility functions for filenames. 3490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch FileInfo provides easy access to the components of a file's path 3510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch relative to the project root. 3520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 3530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, filename): 3550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._filename = filename 3560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def full_name(self): 3580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Make Windows paths like Unix.""" 3590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return os.path.abspath(self._filename).replace('\\', '/') 3600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def repository_name(self): 3620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Full name after removing the local path to the repository. 3630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch If we have a real absolute path name here we can try to do something smart: 3650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch detecting the root of the checkout and truncating /path/to/checkout from 3660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the name so that we get header guards that don't include things like 3670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "C:\Documents and Settings\..." or "/home/username/..." in them and thus 3680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch people on different computers who have checked the source out to different 3690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch locations won't see bogus errors. 3700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 3710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch fullname = self.full_name() 3720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(fullname): 3740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch project_dir = os.path.dirname(fullname) 3750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(os.path.join(project_dir, ".svn")): 3770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If there's a .svn file in the current directory, we 3780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # recursively look up the directory tree for the top 3790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # of the SVN checkout 3800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = project_dir 3810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch one_up_dir = os.path.dirname(root_dir) 3820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while os.path.exists(os.path.join(one_up_dir, ".svn")): 3830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(root_dir) 3840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch one_up_dir = os.path.dirname(one_up_dir) 3850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch prefix = os.path.commonprefix([root_dir, project_dir]) 3870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname[len(prefix) + 1:] 3880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Not SVN? Try to find a git top level directory by 3900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # searching up from the current path. 3910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(fullname) 3920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (root_dir != os.path.dirname(root_dir) 3930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not os.path.exists(os.path.join(root_dir, ".git"))): 3940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch root_dir = os.path.dirname(root_dir) 3950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if os.path.exists(os.path.join(root_dir, ".git")): 3960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch prefix = os.path.commonprefix([root_dir, project_dir]) 3970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname[len(prefix) + 1:] 3980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't know what to do; header guard warnings may be wrong... 4000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return fullname 4010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def split(self): 4030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Splits the file into the directory, basename, and extension. 4040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For 'chrome/browser/browser.cpp', Split() would 4060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ('chrome/browser', 'browser', '.cpp') 4070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 4090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch A tuple of (directory, basename, extension). 4100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 4110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch googlename = self.repository_name() 4130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch project, rest = os.path.split(googlename) 4140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (project,) + os.path.splitext(rest) 4150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def base_name(self): 4170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File base name - text after the final slash, before the final period.""" 4180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.split()[1] 4190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def extension(self): 4210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File extension - text following the final period.""" 4220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.split()[2] 4230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def no_extension(self): 4250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File has no source file extension.""" 4260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return '/'.join(self.split()[0:2]) 4270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def is_source(self): 4290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """File has a source file extension.""" 4300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self.extension()[1:] in ('c', 'cc', 'cpp', 'cxx') 4310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. 4340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( 4350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') 4360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches strings. Escape codes should already be removed by ESCAPES. 4370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') 4380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches characters. Escape codes should already be removed by ESCAPES. 4390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") 4400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches multi-line C++ comments. 4410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# This RE is a little bit more complicated than one might expect, because we 4420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# have to take care of space removals tools so we can handle comments inside 4430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# statements better. 4440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# The current rule is: We only clear spaces from both sides when we're at the 4450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# end of the line. Otherwise, we try to remove spaces from the right side, 4460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# if this doesn't work we try on left side but only if there's a non-character 4470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# on the right. 4480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( 4490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r"""(\s*/\*.*\*/\s*$| 4500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /\*.*\*/\s+| 4510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch \s+/\*.*\*/(?=\W)| 4520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /\*.*\*/)""", re.VERBOSE) 4530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef is_cpp_string(line): 4560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Does line terminate so, that the next symbol is in string constant. 4570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function does not consider single-line nor multi-line comments. 4590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 4610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: is a partial line of code starting from the 0..n. 4620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 4640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True, if next character appended to 'line' is inside a 4650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch string constant. 4660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 4670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" 4690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 4700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef find_next_multi_line_comment_start(lines, line_index): 4730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Find the beginning marker for a multiline comment.""" 4740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 4750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().startswith('/*'): 4760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only return this marker if the comment goes beyond this line 4770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().find('*/', 2) < 0: 4780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return line_index 4790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index += 1 4800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(lines) 4810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef find_next_multi_line_comment_end(lines, line_index): 4840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """We are inside a comment, find the end marker.""" 4850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 4860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if lines[line_index].strip().endswith('*/'): 4870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return line_index 4880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index += 1 4890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(lines) 4900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef remove_multi_line_comments_from_range(lines, begin, end): 4930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Clears a range of lines for multi-line comments.""" 4940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Having // dummy comments makes the lines non-empty, so we will not get 4950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # unnecessary blank line warnings later in the code. 4960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for i in range(begin, end): 4970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines[i] = '// dummy' 4980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 500d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef remove_multi_line_comments(lines, error): 5010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Removes multiline (c-style) comments from lines.""" 5020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index = 0 5030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_index < len(lines): 5040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index_begin = find_next_multi_line_comment_start(lines, line_index) 5050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_index_begin >= len(lines): 5060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 5070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index_end = find_next_multi_line_comment_end(lines, line_index_begin) 5080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_index_end >= len(lines): 509d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_index_begin + 1, 'readability/multiline_comment', 5, 5100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Could not find end of multi-line comment') 5110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 5120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remove_multi_line_comments_from_range(lines, line_index_begin, line_index_end + 1) 5130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_index = line_index_end + 1 5140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef cleanse_comments(line): 5170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Removes //-comments and single-line C-style /* */ comments. 5180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 5200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A line of C++ source. 5210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 5230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The line with single-line comments removed. 5240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch comment_position = line.find('//') 5260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if comment_position != -1 and not is_cpp_string(line[:comment_position]): 5270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line[:comment_position] 5280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # get rid of /* ... */ 5290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) 5300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass CleansedLines(object): 5330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Holds 3 copies of all lines with different preprocessing applied to them. 5340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1) elided member contains lines without strings and comments, 5360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2) lines member contains lines without comments, and 5370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 3) raw member contains all the lines without processing. 5380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch All these three members are of <type 'list'>, and of the same length. 5390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, lines): 5420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.elided = [] 5430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines = [] 5440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.raw_lines = lines 5450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self._num_lines = len(lines) 5460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number in range(len(lines)): 5470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.lines.append(cleanse_comments(lines[line_number])) 5480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = self.collapse_strings(lines[line_number]) 5490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.elided.append(cleanse_comments(elided)) 5500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def num_lines(self): 5520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns the number of lines represented.""" 5530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return self._num_lines 5540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch @staticmethod 5560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def collapse_strings(elided): 5570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Collapses strings and chars on a line to simple "" or '' blocks. 5580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch We nix strings first so we're not fooled by text like '"http://"' 5600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 5620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided: The line being processed. 5630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 5650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The line with collapsed strings. 5660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not _RE_PATTERN_INCLUDE.match(elided): 5680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove escaped characters first to make quote/single quote collapsing 5690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # basic. Things that look like escaped characters shouldn't occur 5700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # outside of strings and chars. 5710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) 5720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) 5730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) 5740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return elided 5750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef close_expression(clean_lines, line_number, pos): 5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """If input points to ( or { or [, finds the position that closes it. 5790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch If lines[line_number][pos] points to a '(' or '{' or '[', finds the the 5810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number/pos that correspond to the closing of the expression. 5820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 5840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 5850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 5860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pos: A position on the line. 5870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 5890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch A tuple (line, line_number, pos) pointer *past* the closing brace, or 5900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (line, len(lines), -1) if we never find a close. Note we ignore 5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch strings and comments when matching; and the line we return is the 5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'cleansed' line at line_number. 5930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 5940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch start_character = line[pos] 5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if start_character not in '({[': 5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (line, clean_lines.num_lines(), -1) 5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if start_character == '(': 6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch end_character = ')' 6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if start_character == '[': 6020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch end_character = ']' 6030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if start_character == '{': 6040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch end_character = '}' 6050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch num_open = line.count(start_character) - line.count(end_character) 6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while line_number < clean_lines.num_lines() and num_open > 0: 6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number += 1 6090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch num_open += line.count(start_character) - line.count(end_character) 6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # OK, now find the end_character that actually got us back to even 6120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch endpos = len(line) 6130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while num_open >= 0: 6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch endpos = line.rfind(')', 0, endpos) 6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch num_open -= 1 # chopped off another ) 6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (line, line_number, endpos + 1) 6170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 619d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_copyright(lines, error): 6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if no Copyright message appears at the top of the file.""" 6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We'll say it should occur by line 10. Don't forget there's a 6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # dummy line at the front. 6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in xrange(1, min(len(lines), 11)): 6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if re.search(r'Copyright', lines[line], re.I): 6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 6270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: # means no copyright line was found 628d0825bca7fe65beaee391d30da42e937db621564Steve Block error(0, 'legal/copyright', 5, 6290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'No copyright message found. ' 6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You should have a line: "Copyright [year] <Copyright Owner>"') 6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_header_guard_cpp_variable(filename): 6340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns the CPP variable that should be used as a header guard. 6350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 6370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of a C++ header file. 6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 6400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The CPP variable that should be used as a header guard in the 6410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch named file. 6420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 645d0825bca7fe65beaee391d30da42e937db621564Steve Block return sub(r'[-.\s]', '_', os.path.basename(filename)) 6460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef check_for_header_guard(filename, lines, error): 6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks that the file contains a header guard. 6500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Logs an error if no #ifndef header guard is present. For other 6520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch headers, checks that the full pathname is used. 6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 6550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the C++ header file. 6560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 6570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 6580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 6590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cppvar = get_header_guard_cpp_variable(filename) 6610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef = None 6630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef_line_number = 0 6640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch define = None 6650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number, line in enumerate(lines): 6660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_split = line.split() 6670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if len(line_split) >= 2: 6680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # find the first occurrence of #ifndef and #define, save arg 6690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not ifndef and line_split[0] == '#ifndef': 6700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # set ifndef to the header guard presented on the #ifndef line. 6710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef = line_split[1] 6720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ifndef_line_number = line_number 6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not define and line_split[0] == '#define': 6740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch define = line_split[1] 675d0825bca7fe65beaee391d30da42e937db621564Steve Block if define and ifndef: 676d0825bca7fe65beaee391d30da42e937db621564Steve Block break 6770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not ifndef or not define or ifndef != define: 679d0825bca7fe65beaee391d30da42e937db621564Steve Block error(0, 'build/header_guard', 5, 6800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'No #ifndef header guard found, suggested CPP variable is: %s' % 6810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cppvar) 6820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 6830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 684d0825bca7fe65beaee391d30da42e937db621564Steve Block # The guard should be File_h. 6850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ifndef != cppvar: 686d0825bca7fe65beaee391d30da42e937db621564Steve Block error(ifndef_line_number, 'build/header_guard', 5, 6870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '#ifndef header guard has wrong style, please use: %s' % cppvar) 6880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 690d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_unicode_replacement_characters(lines, error): 6910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error for each line containing Unicode replacement characters. 6920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch These indicate that either the file contained invalid UTF-8 (likely) 6940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or Unicode replacement characters (which it shouldn't). Note that 6950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch it's possible for this to throw off line numbering if the invalid 6960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch UTF-8 occurred adjacent to a newline. 6970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 6980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 6990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 7000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 7010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number, line in enumerate(lines): 7030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if u'\ufffd' in line: 704d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/utf8', 5, 7050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line contains invalid UTF-8 (or Unicode replacement character).') 7060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 708d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_new_line_at_eof(lines, error): 7090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if there is no newline char at the end of the file. 7100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 7120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file. 7130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 7140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The array lines() was created by adding two newlines to the 7170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # original file (go figure), then splitting on \n. 7180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # To verify that the file ends in \n, we just have to make sure the 7190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # last-but-two element of lines() exists and is empty. 7200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if len(lines) < 3 or lines[-2]: 721d0825bca7fe65beaee391d30da42e937db621564Steve Block error(len(lines) - 2, 'whitespace/ending_newline', 5, 7220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Could not find a newline character at the end of the file.') 7230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 725d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_multiline_comments_and_strings(clean_lines, line_number, error): 7260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if we see /* ... */ or "..." that extend past one line. 7270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch /* ... */ comments are legit inside macros, for one line. 7290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Otherwise, we prefer // comments, so it's ok to warn about the 7300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch other. Likewise, it's ok for strings to extend across multiple 7310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines, as long as a line continuation character (backslash) 7320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch terminates each line. Although not currently prohibited by the C++ 7330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch style guide, it's ugly and unnecessary. We don't do well with either 7340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch in this lint program, so we warn about both. 7350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 7370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 7380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 7390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 7400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 7420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove all \\ (escaped backslashes) from the line. They are OK, and the 7440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # second (escaped) slash may trigger later \" detection erroneously. 7450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace('\\\\', '') 7460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.count('/*') > line.count('*/'): 748d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/multiline_comment', 5, 7490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Complex multi-line /*...*/-style comment found. ' 7500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Lint may give bogus warnings. ' 7510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider replacing these with //-style comments, ' 7520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'with #if 0...#endif, ' 7530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'or with more clearly structured multi-line comments.') 7540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (line.count('"') - line.count('\\"')) % 2: 756d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/multiline_string', 5, 7570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Multi-line string ("...") found. This lint script doesn\'t ' 7580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'do well with such strings, and may give bogus warnings. They\'re ' 7590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ugly and unnecessary, and you should use concatenation instead".') 7600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_THREADING_LIST = ( 7630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('asctime(', 'asctime_r('), 7640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('ctime(', 'ctime_r('), 7650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getgrgid(', 'getgrgid_r('), 7660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getgrnam(', 'getgrnam_r('), 7670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getlogin(', 'getlogin_r('), 7680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getpwnam(', 'getpwnam_r('), 7690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('getpwuid(', 'getpwuid_r('), 7700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('gmtime(', 'gmtime_r('), 7710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('localtime(', 'localtime_r('), 7720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('rand(', 'rand_r('), 7730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('readdir(', 'readdir_r('), 7740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('strtok(', 'strtok_r('), 7750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('ttyname(', 'ttyname_r('), 7760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ) 7770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 779d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_posix_threading(clean_lines, line_number, error): 7800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for calls to thread-unsafe functions. 7810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Much code has been originally written without consideration of 7830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch multi-threading. Also, engineers are relying on their old experience; 7840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch they have learned posix before threading extensions were added. These 7850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tests guide the engineers to use thread-safe functions (when using 7860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch posix directly). 7870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 7880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 7890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 7900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 7910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 7920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 7930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 7940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for single_thread_function, multithread_safe_function in _THREADING_LIST: 7950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch index = line.find(single_thread_function) 7960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 7970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if index >= 0 and (index == 0 or (not line[index - 1].isalnum() 7980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line[index - 1] not in ('_', '.', '>'))): 799d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/threadsafe_fn', 2, 8000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider using ' + multithread_safe_function + 8010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '...) instead of ' + single_thread_function + 8020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '...) for improved thread safety.') 8030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches invalid increment: *count++, which moves pointer instead of 8060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# incrementing a value. 8070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INVALID_INCREMENT = re.compile( 8080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'^\s*\*\w+(\+\+|--);') 8090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 811d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_invalid_increment(clean_lines, line_number, error): 8120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for invalid increment *count++. 8130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example following function: 8150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch void increment_counter(int* count) { 8160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *count++; 8170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 8180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is invalid, because it effectively does count++, moving pointer, and should 8190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch be replaced with ++*count, (*count)++ or *count += 1. 8200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 8220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 8230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 8240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 8250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 8260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 8270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if _RE_PATTERN_INVALID_INCREMENT.match(line): 828d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/invalid_increment', 5, 8290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Changing pointer instead of value (or unused value of operator*).') 8300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _ClassInfo(object): 8330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Stores information about a class.""" 8340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self, name, line_number): 8360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.name = name 8370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.line_number = line_number 8380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.seen_open_brace = False 8390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.is_derived = False 8400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.virtual_method_line_number = None 8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.has_virtual_destructor = False 8420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.brace_depth = 0 8430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass _ClassState(object): 8460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Holds the current state of the parse relating to class declarations. 8470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch It maintains a stack of _ClassInfos representing the parser's guess 8490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch as to the current nesting of class declarations. The innermost class 8500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is at the top (back) of the stack. Typically, the stack will either 8510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch be empty or have exactly one entry. 8520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 8530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch def __init__(self): 8550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.classinfo_stack = [] 8560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 857d0825bca7fe65beaee391d30da42e937db621564Steve Block def check_finished(self, error): 8580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks that all classes have been completely parsed. 8590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Call this when all lines in a file have been processed. 8610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 8620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 8630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 8640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if self.classinfo_stack: 8650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note: This test can result in false positives if #ifdef constructs 8660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # get in the way of brace matching. See the testBuildClass test in 8670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # cpp_style_unittest.py for an example of this. 868d0825bca7fe65beaee391d30da42e937db621564Steve Block error(self.classinfo_stack[0].line_number, 'build/class', 5, 8690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Failed to find complete declaration of class %s' % 8700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch self.classinfo_stack[0].name) 8710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 873643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockclass _FileState(object): 874643ca7872b450ea4efacab6188849e5aac2ba161Steve Block def __init__(self): 875643ca7872b450ea4efacab6188849e5aac2ba161Steve Block self._did_inside_namespace_indent_warning = False 876643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 877643ca7872b450ea4efacab6188849e5aac2ba161Steve Block def set_did_inside_namespace_indent_warning(self): 878643ca7872b450ea4efacab6188849e5aac2ba161Steve Block self._did_inside_namespace_indent_warning = True 879643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 880643ca7872b450ea4efacab6188849e5aac2ba161Steve Block def did_inside_namespace_indent_warning(self): 881643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return self._did_inside_namespace_indent_warning 882643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 883d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_non_standard_constructs(clean_lines, line_number, 8840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state, error): 8850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. 8860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 8870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Complain about several constructs which gcc-2 accepts, but which are 8880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch not standard C++. Warning about these in lint is one way to ease the 8890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch transition to new compilers. 8900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - put storage class first (e.g. "static const" instead of "const static"). 8910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "%lld" instead of %qd" in printf-type functions. 8920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "%1$d" is non-standard in printf-type functions. 8930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - "\%" is an undefined character escape sequence. 8940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - text after #endif is not allowed. 8950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - invalid inner-style forward declaration. 8960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - >? and <? operators, and their >?= and <?= cousins. 8970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch - classes with virtual methods need virtual destructors (compiler warning 8980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch available, but not turned on yet.) 8990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Additionally, check for constructor/destructor style violations as it 9010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is very convenient to do so while checking for gcc-2 compliance. 9020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 9040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 9050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 9060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state: A _ClassState instance which maintains information about 9070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the current stack of nested class declarations being parsed. 908d0825bca7fe65beaee391d30da42e937db621564Steve Block error: A callable to which errors are reported, which takes parameters: 909d0825bca7fe65beaee391d30da42e937db621564Steve Block line number, error level, and message 9100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 9110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove comments from the line, but leave in strings for now. 9130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.lines[line_number] 9140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'printf\s*\(.*".*%[-+ ]?\d*q', line): 916d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf_format', 3, 9170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%q in format strings is deprecated. Use %ll instead.') 9180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'printf\s*\(.*".*%\d+\$', line): 920d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf_format', 2, 9210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%N$ formats are unconventional. Try rewriting to avoid them.') 9220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Remove escaped backslashes before looking for undefined escapes. 9240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = line.replace('\\\\', '') 9250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'("|\').*\\(%|\[|\(|{)', line): 927d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/printf_format', 3, 9280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%, [, (, and { are undefined character escapes. Unescape them.') 9290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For the rest, work with both comments and strings removed. 9310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 9320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\b(const|volatile|void|char|short|int|long' 9340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'|float|double|signed|unsigned' 9350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'|schar|u?int8|u?int16|u?int32|u?int64)' 9360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s+(auto|register|static|extern|typedef)\b', 9370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line): 938d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/storage_class', 5, 9390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Storage class (static, extern, typedef, etc) should be first.') 9400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*#\s*endif\s*[^/\s]+', line): 942d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/endif_comment', 5, 9430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Uncommented text after #endif is non-standard. Use a comment.') 9440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line): 946d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/forward_decl', 5, 9470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Inner-style forward declarations are invalid. Remove this line.') 9480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', line): 950d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/deprecated', 3, 9510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '>? and <? (max and min) operators are non-standard and deprecated.') 9520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Track class entry and exit, and attempt to find cases within the 9540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # class declaration that don't meet the C++ style 9550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # guidelines. Tracking is very dependent on the code matching Google 9560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # style guidelines, but it seems to perform well enough in testing 9570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # to be a worthwhile addition to the checks. 9580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack = class_state.classinfo_stack 9590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for a class declaration 9600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_decl_match = match( 9610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s*(template\s*<[\w\s<>,:]*>\s*)?(class|struct)\s+(\w+(::\w+)*)', line) 9620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if class_decl_match: 9630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack.append(_ClassInfo(class_decl_match.group(3), line_number)) 9640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Everything else in this function uses the top of the stack if it's 9660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # not empty. 9670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo_stack: 9680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 9690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo = classinfo_stack[-1] 9710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the opening brace hasn't been seen look for it and also 9730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # parent class declarations. 9740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo.seen_open_brace: 9750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the line has a ';' in it, assume it's a forward declaration or 9760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a single-line class declaration, which we won't process. 9770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.find(';') != -1: 9780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo_stack.pop() 9790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 9800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.seen_open_brace = (line.find('{') != -1) 9810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for a bare ':' 9820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search('(^|[^:]):($|[^:])', line): 9830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.is_derived = True 9840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not classinfo.seen_open_brace: 9850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return # Everything else in this function is for after open brace 9860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The class may have been declared with namespace or classname qualifiers. 9880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The constructor and destructor will not have those qualifiers. 9890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch base_classname = classinfo.name.split('::')[-1] 9900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 9910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for single-argument constructors that aren't marked explicit. 9920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Technically a valid construct, but against style. 9930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch args = match(r'(?<!explicit)\s+%s\s*\(([^,()]+)\)' 9940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % re.escape(base_classname), 9950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line) 9960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (args 9970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and args.group(1) != 'void' 9980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not match(r'(const\s+)?%s\s*&' % re.escape(base_classname), 9990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch args.group(1).strip())): 1000d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/explicit', 5, 10010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Single-argument constructors should be marked explicit.') 10020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for methods declared virtual. 10040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bvirtual\b', line): 10050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.virtual_method_line_number = line_number 10060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only look for a destructor declaration on the same line. It would 10070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # be extremely unlikely for the destructor declaration to occupy 10080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # more than one line. 10090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'~%s\s*\(' % base_classname, line): 10100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.has_virtual_destructor = True 10110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for class end. 10130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch brace_depth = classinfo.brace_depth 10140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch brace_depth = brace_depth + line.count('{') - line.count('}') 10150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if brace_depth <= 0: 10160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo = classinfo_stack.pop() 10170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Try to detect missing virtual destructor declarations. 10180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For now, only warn if a non-derived class with virtual methods lacks 10190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a virtual destructor. This is to make it less likely that people will 10200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # declare derived virtual destructors without declaring the base 10210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # destructor virtual. 10220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ((classinfo.virtual_method_line_number is not None) 10230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (not classinfo.has_virtual_destructor) 10240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (not classinfo.is_derived)): # Only warn for base classes 1025d0825bca7fe65beaee391d30da42e937db621564Steve Block error(classinfo.line_number, 'runtime/virtual', 4, 10260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'The class %s probably needs a virtual destructor due to ' 10270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'having virtual method(s), one declared at line %d.' 10280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (classinfo.name, classinfo.virtual_method_line_number)) 10290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 10300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch classinfo.brace_depth = brace_depth 10310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1033d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_spacing_for_function_call(line, line_number, error): 10340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for the correctness of various spacing around function calls. 10350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 10370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The text of the line to check. 10380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 10390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 10400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 10410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Since function calls often occur inside if/for/foreach/while/switch 10430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # expressions - which have their own, more liberal conventions - we 10440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # first see if we should be looking inside such an expression for a 10450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function call, to which we can apply more strict standards. 10460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_call = line # if there's no control flow construct, look at whole line 10470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern in (r'\bif\s*\((.*)\)\s*{', 10480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bfor\s*\((.*)\)\s*{', 10490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bforeach\s*\((.*)\)\s*{', 10500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bwhile\s*\((.*)\)\s*[{;]', 10510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\bswitch\s*\((.*)\)\s*{'): 10520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(pattern, line) 10530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 10540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_call = matched.group(1) # look inside the parens for function calls 10550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 10560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Except in if/for/foreach/while/switch, there should never be space 10580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # immediately inside parens (eg "f( 3, 4 )"). We make an exception 10590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # for nested parens ( (a+b) + c ). Likewise, there should never be 10600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a space before a ( when it's a function argument. I assume it's a 10610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function argument when the char before the whitespace is legal in 10620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a function name (alnum + _) and we're not starting a macro. Also ignore 10630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # pointers and references to arrays and functions coz they're too tricky: 10640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # we use a very simple way to recognize these: 10650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)(maybe-something)" or 10660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)(maybe-something," or 10670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # " (something)[something]" 10680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note that we assume the contents of [] to be short enough that 10690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # they'll never need to wrap. 10700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ( # Ignore control structures. 10710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch not search(r'\b(if|for|foreach|while|switch|return|new|delete)\b', function_call) 10720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Ignore pointers/references to functions. 10730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r' \([^)]+\)\([^)]*(\)|,$)', function_call) 10740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Ignore pointers/references to arrays. 10750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r' \([^)]+\)\[[^\]]+\]', function_call)): 10760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\w\s*\([ \t](?!\s*\\$)', function_call): # a ( used for a fn call 1077d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 10780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space after ( in function call') 10790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif search(r'\([ \t]+(?!(\s*\\)|\()', function_call): 1080d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 2, 10810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space after (') 10820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (search(r'\w\s+\(', function_call) 10830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'#\s*define|typedef', function_call)): 1084d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 10850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before ( in function call') 10860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the ) is followed only by a newline or a { + newline, assume it's 10870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # part of a control statement (if/while/etc), and don't complain 10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[^)\s]\s+\)(?!\s*$|{\s*$)', function_call): 1089d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 2, 10900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before )') 10910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef is_blank_line(line): 10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Returns true if the given line is blank. 10950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch We consider a line to be blank if the line is empty or consists of 10970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch only white spaces. 10980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 10990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 11000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A line of a string. 11010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 11030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True, if the given line is blank. 11040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return not line or line.isspace() 11060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1108d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_function_lengths(clean_lines, line_number, function_state, error): 11090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Reports for long function bodies. 11100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For an overview why this is done, see: 11120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions 11130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Uses a simplistic algorithm assuming other style guidelines 11150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (especially spacing) are followed. 11160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Only checks unindented functions, so class members are unchecked. 11170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Trivial bodies are unchecked, so constructors with huge initializer lists 11180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch may be missed. 11190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Blank/comment lines are not counted so as to avoid encouraging the removal 11200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch of vertical space and commments just to get through a lint check. 11210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NOLINT *on the last line of a function* disables this check. 11220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 11240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 11250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 11260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state: Current function name and lines in body so far. 11270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 11280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines = clean_lines.lines 11300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = lines[line_number] 11310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw = clean_lines.raw_lines 11320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_line = raw[line_number] 11330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch joined_line = '' 11340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch starting_func = False 11360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... 11370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_result = match(regexp, line) 11380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match_result: 11390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the name is all caps and underscores, figure it's a macro and 11400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # ignore it, unless it's TEST or TEST_F. 11410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_name = match_result.group(1).split()[-1] 11420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if function_name == 'TEST' or function_name == 'TEST_F' or (not match(r'[A-Z_]+$', function_name)): 11430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch starting_func = True 11440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if starting_func: 11460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch body_found = False 11470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for start_line_number in xrange(line_number, clean_lines.num_lines()): 11480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch start_line = lines[start_line_number] 11490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch joined_line += ' ' + start_line.lstrip() 11500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'(;|})', start_line): # Declarations and trivial functions 11510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch body_found = True 11520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break # ... ignore 11530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'{', start_line): 11540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch body_found = True 11550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function = search(r'((\w|:)*)\(', line).group(1) 11560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'TEST', function): # Handle TEST... macros 11570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch parameter_regexp = search(r'(\(.*\))', joined_line) 11580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if parameter_regexp: # Ignore bad syntax 11590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function += parameter_regexp.group(1) 11600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 11610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function += '()' 11620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state.begin(function) 11630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 11640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not body_found: 11650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # No body for the function (or evidence of a non-function) was found. 1166d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/fn_size', 5, 11670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Lint failed to find start of function body.') 11680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif match(r'^\}\s*$', line): # function end 11690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'\bNOLINT\b', raw_line): 1170d0825bca7fe65beaee391d30da42e937db621564Steve Block function_state.check(error, line_number) 11710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state.end() 11720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not match(r'^\s*$', line): 11730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state.count() # Count non-blank/non-comment lines. 11740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1176d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_spacing(file_extension, clean_lines, line_number, error): 11770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for the correctness of various spacing issues in the code. 11780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Things we check for: spaces around operators, spaces after 11800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if/for/while/switch, no spaces around parens in function calls, two 11810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch spaces between code and comment, don't start a block with a blank 11820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line, don't end a function with a blank line, don't have too many 11830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch blank lines in a row. 11840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 1186d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The current file extension, without the leading dot. 11870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 11880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 11890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 11900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 11910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw = clean_lines.raw_lines 11930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = raw[line_number] 11940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 11950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Before nixing comments, check if the line is blank for no good 11960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # reason. This includes the first line after a block is opened, and 11970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # blank lines at the end of a function (ie, right before a line like '}'). 11980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if is_blank_line(line): 11990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elided = clean_lines.elided 12000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = elided[line_number - 1] 12010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_brace = previous_line.rfind('{') 12020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: Don't complain if line before blank line, and line after, 12030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # both start with alnums and are indented the same amount. 12040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This ignores whitespace at the start of a namespace block 12050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because those are not usually indented. 12060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (previous_brace != -1 and previous_line[previous_brace:].find('}') == -1 12070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and previous_line[:previous_brace].find('namespace') == -1): 12080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # OK, we have a blank line at the start of a code block. Before we 12090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # complain, we check if it is an exception to the rule: The previous 12100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # non-empty line has the parameters of a function header that are indented 12110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 4 spaces (because they did not fit in a 80 column line when placed on 12120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same line as the function name). We also check for the case where 12130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the previous line is indented 6 spaces, which may happen when the 12140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # initializers of a constructor do not fit into a 80 column line. 12150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = False 12160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r' {6}\w', previous_line): # Initializer list? 12170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We are looking for the opening column of initializer list, which 12180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # should be indented 4 spaces to cause 6 space indentation afterwards. 12190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch search_position = line_number - 2 12200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (search_position >= 0 12210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and match(r' {6}\w', elided[search_position])): 12220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch search_position -= 1 12230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = (search_position >= 0 12240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and elided[search_position][:5] == ' :') 12250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 12260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Search for the function arguments or an initializer list. We use a 12270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # simple heuristic here: If the line is indented 4 spaces; and we have a 12280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # closing paren, without the opening paren, followed by an opening brace 12290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or colon (for initializer lists) we assume that it is the last line of 12300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # a function header. If we have a colon indented 4 spaces, it is an 12310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # initializer list. 12320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch exception = (match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', 12330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line) 12340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or match(r' {4}:', previous_line)) 12350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not exception: 1237d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/blank_line', 2, 12380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Blank line at the start of a code block. Is this needed?') 12390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This doesn't ignore whitespace at the end of a namespace block 12400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because that is too hard without pairing open/close braces; 12410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # however, a special exception is made for namespace closing 12420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # brackets which have a comment containing "namespace". 12430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 12440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Also, ignore blank lines at the end of a block in a long if-else 12450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # chain, like this: 12460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if (condition1) { 12470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # // Something followed by a blank line 12480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 12490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } else if (condition2) { 12500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # // Something else 12510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } 12520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line_number + 1 < clean_lines.num_lines(): 12530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch next_line = raw[line_number + 1] 12540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (next_line 12550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and match(r'\s*}', next_line) 12560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and next_line.find('namespace') == -1 12570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and next_line.find('} else ') == -1): 1258d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/blank_line', 3, 12590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Blank line at the end of a code block. Is this needed?') 12600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Next, we complain if there's a comment too near the text 12620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch comment_position = line.find('//') 12630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if comment_position != -1: 12640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if the // may be in quotes. If so, ignore it 12650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 12660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (line.count('"', 0, comment_position) - line.count('\\"', 0, comment_position)) % 2 == 0: # not in quotes 1267d0825bca7fe65beaee391d30da42e937db621564Steve Block # Allow one space before end of line comment. 1268d0825bca7fe65beaee391d30da42e937db621564Steve Block if (not match(r'^\s*$', line[:comment_position]) 1269d0825bca7fe65beaee391d30da42e937db621564Steve Block and (comment_position >= 1 1270d0825bca7fe65beaee391d30da42e937db621564Steve Block and ((line[comment_position - 1] not in string.whitespace) 12710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or (comment_position >= 2 1272d0825bca7fe65beaee391d30da42e937db621564Steve Block and line[comment_position - 2] in string.whitespace)))): 1273d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comments', 5, 1274d0825bca7fe65beaee391d30da42e937db621564Steve Block 'One space before end of line comments') 12750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There should always be a space between the // and the comment 12760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch commentend = comment_position + 2 12770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if commentend < len(line) and not line[commentend] == ' ': 12780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # but some lines are exceptions -- e.g. if they're big 12790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # comment delimiters like: 12800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # //---------------------------------------------------------- 12810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or they begin with multiple slashes followed by a space: 12820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # //////// Header comment 12830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = (search(r'[=/-]{4,}\s*$', line[commentend:]) 12840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or search(r'^/+ ', line[commentend:])) 12850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 1286d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comments', 4, 12870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Should have a space between // and comment') 12880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # get rid of comments and strings 12900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 12910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't try to do spacing checks for operator methods 1292643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) 1293643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Don't try to do spacing checks for #include or #import statements at 1294643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # minimum because it messes up checks for spacing around / 1295643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if match(r'\s*#\s*(?:include|import)', line): 1296cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return 1297cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if search(r'[\w.]=[\w.]', line): 1298d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 12990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing spaces around =') 13000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1301cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block # FIXME: It's not ok to have spaces around binary operators like . 13020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You should always have whitespace around binary operators. 13040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Alas, we can't test < or > because they're legitimately used sans spaces 13050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # (a->b, vector<int> a). The only time we can tell is a < with no >, and 13060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # only if it's not template params list spilling into the next line. 1307231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block matched = search(r'[^<>=!\s](==|!=|\+=|-=|\*=|/=|/|\|=|&=|<<=|>>=|<=|>=|\|\||\||&&|>>|<<)[^<>=!\s]', line) 13080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 13090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note that while it seems that the '<[^<]*' term in the following 13100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # regexp could be simplified to '<.*', which would indeed match 13110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same class of strings, the [^<] means that searching for the 13120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # regexp takes linear rather than quadratic time. 13130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'<[^<]*,\s*$', line): # template params spill 13140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line) 13150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1316d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 3, 13170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing spaces around %s' % matched.group(1)) 13180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There shouldn't be space around unary operators 13200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) 13210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1322d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 13230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space for operator %s' % matched.group(1)) 13240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # A pet peeve of mine: no spaces after an if, while, switch, or for 13260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r' (if\(|for\(|foreach\(|while\(|switch\()', line) 13270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1328d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 5, 13290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before ( in %s' % matched.group(1)) 13300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For if/for/foreach/while/switch, the left and right parens should be 13320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # consistent about how many spaces are inside the parens, and 13330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # there should either be zero or one spaces inside the parens. 13340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We don't want: "if ( foo)" or "if ( foo )". 13350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. 1336d0825bca7fe65beaee391d30da42e937db621564Steve Block matched = search(r'\b(?P<statement>if|for|foreach|while|switch)\s*\((?P<reminder>.*)$', line) 13370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1338d0825bca7fe65beaee391d30da42e937db621564Steve Block statement = matched.group('statement') 1339d0825bca7fe65beaee391d30da42e937db621564Steve Block condition, rest = up_to_unmatched_closing_paren(matched.group('reminder')) 1340d0825bca7fe65beaee391d30da42e937db621564Steve Block if condition is not None: 1341d0825bca7fe65beaee391d30da42e937db621564Steve Block condition_match = search(r'(?P<leading>[ ]*)(?P<separator>.).*[^ ]+(?P<trailing>[ ]*)', condition) 1342d0825bca7fe65beaee391d30da42e937db621564Steve Block if condition_match: 1343d0825bca7fe65beaee391d30da42e937db621564Steve Block n_leading = len(condition_match.group('leading')) 1344d0825bca7fe65beaee391d30da42e937db621564Steve Block n_trailing = len(condition_match.group('trailing')) 1345d0825bca7fe65beaee391d30da42e937db621564Steve Block if n_leading != n_trailing: 1346d0825bca7fe65beaee391d30da42e937db621564Steve Block for_exception = statement == 'for' and ( 1347d0825bca7fe65beaee391d30da42e937db621564Steve Block (condition.startswith(' ;') and n_trailing == 0) or 1348d0825bca7fe65beaee391d30da42e937db621564Steve Block (condition.endswith('; ') and n_leading == 0)) 1349d0825bca7fe65beaee391d30da42e937db621564Steve Block if not for_exception: 1350d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 5, 1351d0825bca7fe65beaee391d30da42e937db621564Steve Block 'Mismatching spaces inside () in %s' % statement) 1352d0825bca7fe65beaee391d30da42e937db621564Steve Block if n_leading > 1: 1353d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 5, 1354d0825bca7fe65beaee391d30da42e937db621564Steve Block 'Should have zero or one spaces inside ( and ) in %s' % 1355d0825bca7fe65beaee391d30da42e937db621564Steve Block statement) 1356d0825bca7fe65beaee391d30da42e937db621564Steve Block 1357d0825bca7fe65beaee391d30da42e937db621564Steve Block # Do not check for more than one command in macros 1358d0825bca7fe65beaee391d30da42e937db621564Steve Block in_macro = match(r'\s*#define', line) 1359d0825bca7fe65beaee391d30da42e937db621564Steve Block if not in_macro and not match(r'((\s*{\s*}?)|(\s*;?))\s*\\?$', rest): 1360d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/parens', 4, 1361d0825bca7fe65beaee391d30da42e937db621564Steve Block 'More than one command on the same line in %s' % statement) 13620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You should always have a space after a comma (either as fn arg or operator) 13640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r',[^\s]', line): 1365d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/comma', 3, 13660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space after ,') 13670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1368d0825bca7fe65beaee391d30da42e937db621564Steve Block if file_extension == 'cpp': 13690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # C++ should have the & or * beside the type not the variable name. 13700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = match(r'\s*\w+(?<!\breturn)\s+(?P<pointer_operator>\*|\&)\w+', line) 13710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1372d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/declaration', 3, 13730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Declaration has space between type name and %s in %s' % (matched.group('pointer_operator'), matched.group(0).strip())) 13740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1375d0825bca7fe65beaee391d30da42e937db621564Steve Block elif file_extension == 'c': 13760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # C Pointer declaration should have the * beside the variable not the type name. 13770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'^\s*\w+\*\s+\w+', line) 13780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 1379d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/declaration', 3, 13800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Declaration has space between * and variable name in %s' % matched.group(0).strip()) 13810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Next we will look for issues with function calls. 1383d0825bca7fe65beaee391d30da42e937db621564Steve Block check_spacing_for_function_call(line, line_number, error) 13840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Except after an opening paren, you should have spaces before your braces. 13860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # And since you should never have braces at the beginning of a line, this is 13870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # an easy test. 13880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[^ ({]{', line): 1389d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 13900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before {') 13910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Make sure '} else {' has spaces. 13930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'}else', line): 1394d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 13950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Missing space before else') 13960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 13970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You shouldn't have spaces before your brackets, except maybe after 13980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 'delete []' or 'new char * []'. 13990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\w\s+\[', line) and not search(r'delete\s+\[', line): 1400d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 5, 14010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before [') 14020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # You shouldn't have a space before a semicolon at the end of the line. 14040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There's a special case for "for" since the style guide allows space before 14050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the semicolon there. 14060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r':\s*;\s*$', line): 1407d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 14080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Semicolon defining empty statement. Use { } instead.') 14090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif search(r'^\s*;\s*$', line): 1410d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 14110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line contains only semicolon. If this should be an empty statement, ' 14120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'use { } instead.') 14130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\s+;\s*$', line) and not search(r'\bfor\b', line)): 1414d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 14150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Extra space before last semicolon. If this should be an empty ' 14160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'statement, use { } instead.') 14170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\b(for|while)\s*\(.*\)\s*;\s*$', line) 14180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('(') == line.count(')') 14190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Allow do {} while(); 14200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'}\s*while', line)): 1421d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/semicolon', 5, 14220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Semicolon defining empty statement for this loop. Use { } instead.') 14230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_previous_non_blank_line(clean_lines, line_number): 14260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Return the most recent non-blank line and its line number. 14270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 14290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file contents. 14300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 14310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 14330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch A tuple with two elements. The first element is the contents of the last 14340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch non-blank line before the current line, or the empty string if this is the 14350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch first non-blank line. The second is the line number of that line, or -1 14360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if this is the first non-blank line. 14370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 14380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number - 1 14400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while previous_line_number >= 0: 14410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.elided[previous_line_number] 14420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_blank_line(previous_line): # if not a blank line... 14430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (previous_line, previous_line_number) 14440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number -= 1 14450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return ('', -1) 14460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1448d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error): 14490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for indentation errors inside of namespaces. 14500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 14520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 14530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 14540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 1455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 1456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 14570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 14580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 14590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 14610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 14620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch namespace_match = match(r'(?P<namespace_indentation>\s*)namespace\s+\S+\s*{\s*$', line) 14630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not namespace_match: 14640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 14650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1466cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block current_indentation_level = len(namespace_match.group('namespace_indentation')) 1467cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if current_indentation_level > 0: 1468643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Don't warn about an indented namespace if we already warned about indented code. 1469643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not file_state.did_inside_namespace_indent_warning(): 1470d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/indent', 4, 1471643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 'namespace should never be indented.') 1472cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block return 1473cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = False; 14740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 1475cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block in_preprocessor_directive = False; 1476cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block for current_line in clean_lines.elided[line_number + 1:]: 1477cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block line_offset += 1 1478cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not current_line.strip(): 1479cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block continue 1480cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not current_indentation_level: 1481cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if not (in_preprocessor_directive or looking_for_semicolon): 1482643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not match(r'\S', current_line) and not file_state.did_inside_namespace_indent_warning(): 1483643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state.set_did_inside_namespace_indent_warning() 1484d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 1485cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block 'Code inside a namespace should not be indented.') 1486cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if in_preprocessor_directive or (current_line.strip()[0] == '#'): # This takes care of preprocessor directive syntax. 1487cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block in_preprocessor_directive = current_line[-1] == '\\' 1488cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block else: 1489cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = ((current_line.find(';') == -1) and (current_line.strip()[-1] != '}')) or (current_line[-1] == '\\') 1490cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block else: 1491cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block looking_for_semicolon = False; # If we have a brace we may not need a semicolon. 1492cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block current_indentation_level += current_line.count('{') - current_line.count('}') 1493cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if current_indentation_level < 0: 1494cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block break; 14950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1496d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_using_std(file_extension, clean_lines, line_number, error): 1497231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """Looks for 'using std::foo;' statements which should be replaced with 'using namespace std;'. 1498231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1499231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Args: 1500d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The extension of the current file, without the leading dot. 1501231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block clean_lines: A CleansedLines instance containing the file. 1502231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line_number: The number of the line to check. 1503231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block error: The function to call with any errors found. 1504231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """ 1505231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1506231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block # This check doesn't apply to C or Objective-C implementation files. 1507d0825bca7fe65beaee391d30da42e937db621564Steve Block if is_c_or_objective_c(file_extension): 1508231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1509231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1510231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line = clean_lines.elided[line_number] # Get rid of comments and strings. 1511231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1512231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block using_std_match = match(r'\s*using\s+std::(?P<method_name>\S+)\s*;\s*$', line) 1513231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if not using_std_match: 1514231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1515231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1516231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block method_name = using_std_match.group('method_name') 1517d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/using_std', 4, 1518231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block "Use 'using namespace std;' instead of 'using std::%s;'." % method_name) 1519231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1520231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1521d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_max_min_macros(file_extension, clean_lines, line_number, error): 1522231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """Looks use of MAX() and MIN() macros that should be replaced with std::max() and std::min(). 1523231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1524231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Args: 1525d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The extension of the current file, without the leading dot. 1526231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block clean_lines: A CleansedLines instance containing the file. 1527231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line_number: The number of the line to check. 1528231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block error: The function to call with any errors found. 1529231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block """ 1530231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1531231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block # This check doesn't apply to C or Objective-C implementation files. 1532d0825bca7fe65beaee391d30da42e937db621564Steve Block if is_c_or_objective_c(file_extension): 1533231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1534231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1535231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block line = clean_lines.elided[line_number] # Get rid of comments and strings. 1536231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1537231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macros_search = search(r'\b(?P<max_min_macro>(MAX|MIN))\s*\(', line) 1538231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if not max_min_macros_search: 1539231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 1540231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1541231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macro = max_min_macros_search.group('max_min_macro') 1542231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block max_min_macro_lower = max_min_macro.lower() 1543d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/max_min_macros', 4, 1544231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 'Use std::%s() or std::%s<type>() instead of the %s() macro.' 1545231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block % (max_min_macro_lower, max_min_macro_lower, max_min_macro)) 1546231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1547231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 1548d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_switch_indentation(clean_lines, line_number, error): 15490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for indentation errors inside of switch statements. 15500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 15520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 15530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 15540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 15550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 15560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 15580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch_match = match(r'(?P<switch_indentation>\s*)switch\s*\(.+\)\s*{\s*$', line) 15600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not switch_match: 15610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 15620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch switch_indentation = switch_match.group('switch_indentation') 15640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch inner_indentation = switch_indentation + ' ' * 4 15650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 15660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_nested_switch = False 15670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for current_line in clean_lines.elided[line_number + 1:]: 15690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset += 1 15700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip not only empty lines but also those with preprocessor directives. 15720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line.strip() == '' or current_line.startswith('#'): 15730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 15740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*switch\s*\(.+\)\s*{\s*$', current_line): 15760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Complexity alarm - another switch statement nested inside the one 15770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that we're currently testing. We'll need to track the extent of 15780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that inner switch if the upcoming label tests are still supposed 15790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # to work correctly. Let's not do that; instead, we'll finish 15800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # checking this line, and then leave it like that. Assuming the 15810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # indentation is done consistently (even if incorrectly), this will 15820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # still catch all indentation issues in practice. 15830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_nested_switch = True 15840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line); 15860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation = current_indentation_match.group('indentation') 15870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remaining_line = current_indentation_match.group('remaining_line') 15880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 15890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # End the check at the end of the switch statement. 15900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if remaining_line.startswith('}') and current_indentation == switch_indentation: 15910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 15920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Case and default branches should not be indented. The regexp also 15930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # catches single-line cases like "default: break;" but does not trigger 15940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # on stuff like "Document::Foo();". 15950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif match(r'(default|case\s+.*)\s*:([^:].*)?$', remaining_line): 15960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation != switch_indentation: 1597d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 15980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'A case label should not be indented, but line up with its switch statement.') 15990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't throw an error for multiple badly indented labels, 16000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one should be enough to figure out the problem. 16010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 16020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We ignore goto labels at the very beginning of a line. 16030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif match(r'\w+\s*:\s*$', remaining_line): 16040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 16050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # It's not a goto label, so check if it's indented at least as far as 16060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the switch statement plus one more level of indentation. 16070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not current_indentation.startswith(inner_indentation): 1608d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'whitespace/indent', 4, 16090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Non-label code inside switch statements should be indented.') 16100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't throw an error for multiple badly indented statements, 16110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one should be enough to figure out the problem. 16120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 16130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if encountered_nested_switch: 16150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 16160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1618d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_braces(clean_lines, line_number, error): 16190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for misplaced braces (e.g. at the end of line). 16200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 16220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 16230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 16240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 16250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 16260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 16280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*{\s*$', line): 16300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We allow an open brace to start a line in the case where someone 16310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # is using braces for function definition or in a block to 16320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # explicitly create a new scope, which is commonly used to control 16330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the lifetime of stack-allocated variables. We don't detect this 16340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # perfectly: we just don't complain if the last non-whitespace 16350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # character on the previous non-blank line is ';', ':', '{', '}', 16360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # ')', or ') const' and doesn't begin with 'if|for|while|switch|else'. 16370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We also allow '#' for #endif and '=' for array initialization. 16380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = get_previous_non_blank_line(clean_lines, line_number)[0] 16390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if ((not search(r'[;:}{)=]\s*$|\)\s*const\s*$', previous_line) 16400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or search(r'\b(if|for|foreach|while|switch|else)\b', previous_line)) 16410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and previous_line.find('#') < 0): 1642d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 16430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'This { should be at the end of the previous line') 16440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif (search(r'\)\s*(const\s*)?{\s*$', line) 16450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('(') == line.count(')') 1646643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and not search(r'\b(if|for|foreach|while|switch)\b', line) 1647643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and not match(r'\s+[A-Z_][A-Z_0-9]+\b', line)): 1648d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 16490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Place brace on its own line for function definitions.') 16500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (match(r'\s*}\s*(else\s*({\s*)?)?$', line) and line_number > 1): 16520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We check if a closed brace has started a line to see if a 16530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # one line control statement was previous. 16540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.elided[line_number - 2] 16550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (previous_line.find('{') > 0 16560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and search(r'\b(if|for|foreach|while|else)\b', previous_line)): 1657d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/braces', 4, 16580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'One line control clauses should not use braces.') 16590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # An else clause should be on the same line as the preceding closing brace. 16610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*else\s*', line): 16620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = get_previous_non_blank_line(clean_lines, line_number)[0] 16630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*}\s*$', previous_line): 1664d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 16650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else should appear on the same line as the preceding }') 16660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Likewise, an else should never have the else clause on the same line 16680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\belse [^\s{]', line) and not search(r'\belse if\b', line): 1669d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 16700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Else clause should never be on same line as else (use 2 lines)') 16710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In the same way, a do/while should never be on one line 16730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s*do [^\s{]', line): 1674d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 16750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'do/while clauses should not be on a single line') 16760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Braces shouldn't be followed by a ; unless they're defining a struct 16780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # or initializing an array. 16790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We can't tell in general, but we can for some common cases. 16800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number 16810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while True: 16820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (previous_line, previous_line_number) = get_previous_non_blank_line(clean_lines, previous_line_number) 16830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\s+{.*}\s*;', line) and not previous_line.count(';'): 16840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = previous_line + line 16850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 16860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 16870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (search(r'{.*}\s*;', line) 16880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line.count('{') == line.count('}') 16890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'struct|class|enum|\s*=\s*{', line)): 1690d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/braces', 4, 16910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "You don't need a ; after a }") 16920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1694d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_exit_statement_simplifications(clean_lines, line_number, error): 16950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Looks for else or else-if statements that should be written as an 16960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if statement when the prior if concludes with a return, break, continue or 16970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch goto statement. 16980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 16990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 17000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 17010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 17020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 17030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 17040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # Get rid of comments and strings. 17060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else_match = match(r'(?P<else_indentation>\s*)(\}\s*)?else(\s+if\s*\(|(?P<else>\s*(\{\s*)?\Z))', line) 17080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not else_match: 17090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 17100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else_indentation = else_match.group('else_indentation') 17120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch inner_indentation = else_indentation + ' ' * 4 17130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_lines = clean_lines.elided[:line_number] 17150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_lines.reverse() 17160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset = 0 17170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_exit_statement = False 17180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for current_line in previous_lines: 17200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_offset -= 1 17210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip not only empty lines but also those with preprocessor directives 17230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # and goto labels. 17240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line.strip() == '' or current_line.startswith('#') or match(r'\w+\s*:\s*$', current_line): 17250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 17260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip lines with closing braces on the original indentation level. 17280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Even though the styleguide says they should be on the same line as 17290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the "else if" statement, we also want to check for instances where 17300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the current code does not comply with the coding style. Thus, ignore 17310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # these lines and proceed to the line before that. 17320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line == else_indentation + '}': 17330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 17340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation_match = match(r'(?P<indentation>\s*)(?P<remaining_line>.*)$', current_line); 17360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_indentation = current_indentation_match.group('indentation') 17370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remaining_line = current_indentation_match.group('remaining_line') 17380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # As we're going up the lines, the first real statement to encounter 17400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # has to be an exit statement (return, break, continue or goto) - 17410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # otherwise, this check doesn't apply. 17420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not encountered_exit_statement: 17430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We only want to find exit statements if they are on exactly 17440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the same level of indentation as expected from the code inside 17450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the block. If the indentation doesn't strictly match then we 17460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # might have a nested if or something, which must be ignored. 17470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation != inner_indentation: 17480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 17490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(return(\W+.*)|(break|continue)\s*;|goto\s*\w+;)$', remaining_line): 17500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch encountered_exit_statement = True 17510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 17520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 17530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # When code execution reaches this point, we've found an exit statement 17550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # as last statement of the previous block. Now we only need to make 17560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # sure that the block belongs to an "if", then we can throw an error. 17570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip lines with opening braces on the original indentation level, 17590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # similar to the closing braces check above. ("if (condition)\n{") 17600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_line == else_indentation + '{': 17610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 17620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Skip everything that's further indented than our "else" or "else if". 17640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if current_indentation.startswith(else_indentation) and current_indentation != else_indentation: 17650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 17660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # So we've got a line with same (or less) indentation. Is it an "if"? 17680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If yes: throw an error. If no: don't throw an error. 17690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Whatever the outcome, this is the end of our loop. 17700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'if\s*\(', remaining_line): 17710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if else_match.start('else') != -1: 1772d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'readability/control_flow', 4, 17730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else statement can be removed when the prior "if" ' 17740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'concludes with a return, break, continue or goto statement.') 17750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 1776d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number + line_offset, 'readability/control_flow', 4, 17770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'An else if statement should be written as an if statement ' 17780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'when the prior "if" concludes with a return, break, ' 17790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'continue or goto statement.') 17800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 17810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef replaceable_check(operator, macro, line): 17840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Determine whether a basic CHECK can be replaced with a more specific one. 17850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example suggest using CHECK_EQ instead of CHECK(a == b) and 17870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. 17880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 17900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch operator: The C++ operator used in the CHECK. 17910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch macro: The CHECK or EXPECT macro being called. 17920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The current source line. 17930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 17950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True if the CHECK can be replaced with a more specific one. 17960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 17970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 17980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This matches decimal and hex integers, strings, and chars (in that order). 17990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' 18000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Expression to match two sides of the operator with something that 18020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # looks like a literal, since CHECK(x == iterator) won't compile. 18030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This means we can't catch all the cases where a more specific 18040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # CHECK is possible, but it's less annoying than dealing with 18050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # extraneous warnings. 18060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_this = (r'\s*' + macro + r'\((\s*' + 18070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch match_constant + r'\s*' + operator + r'[^<>].*|' 18080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'.*[^<>]' + operator + r'\s*' + match_constant + 18090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\s*\))') 18100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't complain about CHECK(x == NULL) or similar because 18120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # CHECK_EQ(x, NULL) won't compile (requires a cast). 18130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Also, don't complain about more complex boolean expressions 18140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # involving && or || such as CHECK(a == b || c == d). 18150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return match(match_this, line) and not search(r'NULL|&&|\|\|', line) 18160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1818d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_check(clean_lines, line_number, error): 18190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks the use of CHECK and EXPECT macros. 18200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 18220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 18230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 18240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 18250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 18260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Decide the set of replacement macros that should be suggested 18280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 18290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro = '' 18300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for macro in _CHECK_MACROS: 18310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if raw_lines[line_number].find(macro) >= 0: 18320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro = macro 18330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 18340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not current_macro: 18350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' 18360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 18370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] # get rid of comments and strings 18390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. 18410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for operator in ['==', '!=', '>=', '>', '<=', '<']: 18420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if replaceable_check(operator, current_macro, line): 1843d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/check', 2, 18440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Consider using %s instead of %s(a %s b)' % ( 18450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CHECK_REPLACEMENT[current_macro][operator], 18460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch current_macro, operator)) 18470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 18480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1850d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_comparisons_to_zero(clean_lines, line_number, error): 18510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Get the line without comments and strings. 18520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 18530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Include NULL here so that users don't have to convert NULL to 0 first and then get this error. 18550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'[=!]=\s*(NULL|0|true|false)\W', line) or search(r'\W(NULL|0|true|false)\s*[=!]=', line): 1856d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/comparison_to_zero', 5, 18570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Tests for true/false, null/non-null, and zero/non-zero should all be done without equality comparisons.') 18580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1860d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_for_null(file_extension, clean_lines, line_number, error): 18610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This check doesn't apply to C or Objective-C implementation files. 1862d0825bca7fe65beaee391d30da42e937db621564Steve Block if is_c_or_objective_c(file_extension): 18630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 18640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 1866d0825bca7fe65beaee391d30da42e937db621564Steve Block 1867d0825bca7fe65beaee391d30da42e937db621564Steve Block # Don't warn about NULL usage in g_object_{get,set}(). See Bug 32858 1868d0825bca7fe65beaee391d30da42e937db621564Steve Block if search(r'\bg_object_[sg]et\b', line): 1869d0825bca7fe65beaee391d30da42e937db621564Steve Block return 1870d0825bca7fe65beaee391d30da42e937db621564Steve Block 18710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNULL\b', line): 1872d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/null', 5, 'Use 0 instead of NULL.') 18730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 18740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.raw_lines[line_number] 18760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # See if NULL occurs in any comments in the line. If the search for NULL using the raw line 18770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # matches, then do the check with strings collapsed to avoid giving errors for 18780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # NULLs occurring in strings. 18790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNULL\b', line) and search(r'\bNULL\b', CleansedLines.collapse_strings(line)): 1880d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/null', 4, 'Use 0 instead of NULL.') 18810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef get_line_width(line): 18830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Determines the width of the line in column positions. 18840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 18860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: A string, which may be a Unicode string. 18870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 18880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 18890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The width of the line in column positions, accounting for Unicode 18900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch combining characters and wide characters. 18910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 18920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if isinstance(line, unicode): 18930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width = 0 18940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for c in unicodedata.normalize('NFC', line): 18950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if unicodedata.east_asian_width(c) in ('W', 'F'): 18960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width += 2 18970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not unicodedata.combining(c): 18980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch width += 1 18990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return width 19000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return len(line) 19010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1903d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_style(clean_lines, line_number, file_extension, file_state, error): 19040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks rules from the 'C++ style rules' section of cppguide.html. 19050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Most of these rules are hard to test (naming, comment style), but we 19070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch do what we can. In particular we check for 4-space indents, line lengths, 19080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tab usage, spaces inside code, etc. 19090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 19110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 19120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 19130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (without the dot) of the filename. 1914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 1915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 19160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 19170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 19180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 19200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = raw_lines[line_number] 19210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line.find('\t') != -1: 1923d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/tab', 1, 19240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Tab found; better to use spaces') 19250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # One or three blank spaces at the beginning of the line is weird; it's 19270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # hard to reconcile that with 4-space indents. 19280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # NOTE: here are the conditions rob pike used for his tests. Mine aren't 19290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces 19300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(RLENGTH > 20) complain = 0; 19310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match($0, " +(error|private|public|protected):")) complain = 0; 19320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "&& *$")) complain = 0; 19330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "\\|\\| *$")) complain = 0; 19340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, "[\",=><] *$")) complain = 0; 19350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match($0, " <<")) complain = 0; 19360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(match(prev, " +for \\(")) complain = 0; 19370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # if(prevodd && match(prevprev, " +for \\(")) complain = 0; 19380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch initial_spaces = 0 19390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cleansed_line = clean_lines.elided[line_number] 19400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while initial_spaces < len(line) and line[initial_spaces] == ' ': 19410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch initial_spaces += 1 19420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if line and line[-1].isspace(): 1943d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/end_of_line', 4, 19440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Line ends in whitespace. Consider deleting these extra spaces.') 19450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There are certain situations we allow one space, notably for labels 19460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif ((initial_spaces >= 1 and initial_spaces <= 3) 19470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not match(r'\s*\w+\s*:\s*$', cleansed_line)): 1948d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/indent', 3, 19490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Weird number of spaces at line-start. ' 19500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Are you using a 4-space indent?') 19510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Labels should always be indented at least one space. 19520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif not initial_spaces and line[:2] != '//': 19530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch label_match = match(r'(?P<label>[^:]+):\s*$', line) 19540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if label_match: 19560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch label = label_match.group('label') 19570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only throw errors for stuff that is definitely not a goto label, 19580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # because goto labels can in fact occur at the start of the line. 19590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if label in ['public', 'private', 'protected'] or label.find(' ') != -1: 1960d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/labels', 4, 19610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Labels should always be indented at least one space. ' 19620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'If this is a member-initializer list in a constructor, ' 19630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'the colon should be on the line after the definition header.') 19640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (cleansed_line.count(';') > 1 19660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # for loops are allowed two ;'s (and may run over two lines). 19670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and cleansed_line.find('for') == -1 19680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and (get_previous_non_blank_line(clean_lines, line_number)[0].find('for') == -1 19690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or get_previous_non_blank_line(clean_lines, line_number)[0].find(';') != -1) 19700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # It's ok to have many commands in a switch case that fits in 1 line 19710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not ((cleansed_line.find('case ') != -1 19720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or cleansed_line.find('default:') != -1) 1973d0825bca7fe65beaee391d30da42e937db621564Steve Block and cleansed_line.find('break;') != -1) 1974d0825bca7fe65beaee391d30da42e937db621564Steve Block and not cleansed_line.startswith('#define ')): 1975d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/newline', 4, 19760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'More than one command on the same line') 19770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if cleansed_line.strip().endswith('||') or cleansed_line.strip().endswith('&&'): 1979d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'whitespace/operators', 4, 19800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Boolean expressions that span multiple lines should have their ' 19810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'operators on the left side of the line instead of the right side.') 19820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Some more style checks 1984d0825bca7fe65beaee391d30da42e937db621564Steve Block check_namespace_indentation(clean_lines, line_number, file_extension, file_state, error) 1985d0825bca7fe65beaee391d30da42e937db621564Steve Block check_using_std(file_extension, clean_lines, line_number, error) 1986d0825bca7fe65beaee391d30da42e937db621564Steve Block check_max_min_macros(file_extension, clean_lines, line_number, error) 1987d0825bca7fe65beaee391d30da42e937db621564Steve Block check_switch_indentation(clean_lines, line_number, error) 1988d0825bca7fe65beaee391d30da42e937db621564Steve Block check_braces(clean_lines, line_number, error) 1989d0825bca7fe65beaee391d30da42e937db621564Steve Block check_exit_statement_simplifications(clean_lines, line_number, error) 1990d0825bca7fe65beaee391d30da42e937db621564Steve Block check_spacing(file_extension, clean_lines, line_number, error) 1991d0825bca7fe65beaee391d30da42e937db621564Steve Block check_check(clean_lines, line_number, error) 1992d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_comparisons_to_zero(clean_lines, line_number, error) 1993d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_null(file_extension, clean_lines, line_number, error) 19940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 19960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') 19970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') 19980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# Matches the first component of a filename delimited by -s and _s. That is: 19990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' 20000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo.cpp').group(0) == 'foo' 20010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo-bar_baz.cpp').group(0) == 'foo' 20020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch# _RE_FIRST_COMPONENT.match('foo_bar-baz.cpp').group(0) == 'foo' 20030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') 20040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef _drop_common_suffixes(filename): 20070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Drops common suffixes like _test.cpp or -inl.h from filename. 20080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example: 20100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo-inl.h') 20110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo' 20120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/bar/foo.cpp') 20130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/bar/foo' 20140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo_internal.h') 20150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo' 20160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _drop_common_suffixes('foo/foo_unusualinternal.h') 20170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'foo/foo_unusualinternal' 20180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 20200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The input filename. 20210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 20230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The filename with the common suffix removed. 20240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 20250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for suffix in ('test.cpp', 'regtest.cpp', 'unittest.cpp', 20260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'inl.h', 'impl.h', 'internal.h'): 20270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (filename.endswith(suffix) and len(filename) > len(suffix) 20280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and filename[-len(suffix) - 1] in ('-', '_')): 20290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return filename[:-len(suffix) - 1] 20300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return os.path.splitext(filename)[0] 20310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef _classify_include(filename, include, is_system, include_state): 20340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Figures out what kind of header 'include' is. 20350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 20370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The current file cpp_style is running over. 20380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include: The path to a #included file. 20390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_system: True if the #include used <> rather than "". 20400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 20410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 20430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch One of the _XXX_HEADER constants. 20440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch For example: 20460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'config.h', False) 20470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _CONFIG_HEADER 20480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'foo.h', False) 20490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _PRIMARY_HEADER 20500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch >>> _classify_include('foo.cpp', 'bar.h', False) 20510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _OTHER_HEADER 20520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 20530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If it is a system header we know it is classified as _OTHER_HEADER. 20550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if is_system: 20560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER 20570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the include is named config.h then this is WebCore/config.h. 20590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if include == "config.h": 20600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _CONFIG_HEADER 20610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # There cannot be primary includes in header files themselves. Only an 20630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include exactly matches the header filename will be is flagged as 20640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # primary, so that it triggers the "don't include yourself" check. 20650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename.endswith('.h') and filename != include: 20660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER; 20670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2068d0825bca7fe65beaee391d30da42e937db621564Steve Block # Qt's moc files do not follow the naming and ordering rules, so they should be skipped 2069d0825bca7fe65beaee391d30da42e937db621564Steve Block if include.startswith('moc_') and include.endswith('.cpp'): 2070d0825bca7fe65beaee391d30da42e937db621564Steve Block return _MOC_HEADER 2071d0825bca7fe65beaee391d30da42e937db621564Steve Block 2072d0825bca7fe65beaee391d30da42e937db621564Steve Block if include.endswith('.moc'): 2073d0825bca7fe65beaee391d30da42e937db621564Steve Block return _MOC_HEADER 2074d0825bca7fe65beaee391d30da42e937db621564Steve Block 20750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the target file basename starts with the include we're checking 20760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # then we consider it the primary header. 20770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch target_base = FileInfo(filename).base_name() 20780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_base = FileInfo(include).base_name() 20790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we haven't encountered a primary header, then be lenient in checking. 2081643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not include_state.visited_primary_section() and target_base.find(include_base) != -1: 20820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _PRIMARY_HEADER 20830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we already encountered a primary header, perform a strict comparison. 20840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In case the two filename bases are the same then the above lenient check 20850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # probably was a false positive. 20860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif include_state.visited_primary_section() and target_base == include_base: 2087d0825bca7fe65beaee391d30da42e937db621564Steve Block if include == "ResourceHandleWin.h": 2088d0825bca7fe65beaee391d30da42e937db621564Steve Block # FIXME: Thus far, we've only seen one example of these, but if we 2089d0825bca7fe65beaee391d30da42e937db621564Steve Block # start to see more, please consider generalizing this check 2090d0825bca7fe65beaee391d30da42e937db621564Steve Block # somehow. 2091d0825bca7fe65beaee391d30da42e937db621564Steve Block return _OTHER_HEADER 20920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _PRIMARY_HEADER 20930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return _OTHER_HEADER 20950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 20960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2097d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_include_line(filename, file_extension, clean_lines, line_number, include_state, error): 20980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Check rules that are applicable to #include lines. 20990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Strings on #include lines are NOT removed from elided line, to make 21010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch certain tasks easier. However, to prevent false positives, checks 21020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch applicable to #include lines in CheckLanguage must be put here. 21030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 21050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 2106d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: The current file extension, without the leading dot. 21070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 21080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 21090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 21100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 21110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 21128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # FIXME: For readability or as a possible optimization, consider 21138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # exiting early here by checking whether the "build/include" 21148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # category should be checked for the given filename. This 21158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # may involve having the error handler classes expose a 21168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # should_check() method, in addition to the usual __call__ 21178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block # method. 21180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.lines[line_number] 21190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(line) 21210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 21220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 21230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include = matched.group(2) 21250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_system = (matched.group(1) == '<') 21260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for any of the stream classes that are part of standard C++. 21280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): 21298a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block error(line_number, 'readability/streams', 3, 21308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block 'Streams are highly discouraged.') 21310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Look for specific includes to fix. 21330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if include.startswith('wtf/') and not is_system: 2134d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include', 4, 21350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'wtf includes should be <wtf/file.h> instead of "wtf/file.h".') 21360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch duplicate_header = include in include_state 21380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if duplicate_header: 2139d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include', 4, 21400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '"%s" already included at %s:%s' % 21410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (include, filename, include_state[include])) 21420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 21430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state[include] = line_number 21440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_type = _classify_include(filename, include, is_system, include_state) 21460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state.header_types[line_number] = header_type 21470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Only proceed if this isn't a duplicate header. 21490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if duplicate_header: 21500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 21510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We want to ensure that headers appear in the right order: 21530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 1) for implementation files: config.h, primary header, blank line, alphabetically sorted 21540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 2) for header files: alphabetically sorted 21550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The include_state object keeps track of the last type seen 21560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # and complains if the header types are out of order or missing. 2157d0825bca7fe65beaee391d30da42e937db621564Steve Block error_message = include_state.check_next_include_order(header_type, file_extension == "h") 21580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to make sure we have a blank line after primary header. 21600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not error_message and header_type == _PRIMARY_HEADER: 21610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch next_line = clean_lines.raw_lines[line_number + 1] 21620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_blank_line(next_line): 2163d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 21640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You should add a blank line after implementation file\'s own header.') 21650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to make sure all headers besides config.h and the primary header are 2167d0825bca7fe65beaee391d30da42e937db621564Steve Block # alphabetically sorted. Skip Qt's moc files. 21680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not error_message and header_type == _OTHER_HEADER: 21690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number = line_number - 1; 21700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.lines[previous_line_number] 21710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_match = _RE_PATTERN_INCLUDE.search(previous_line) 21720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (not previous_match and previous_line_number > 0 21730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and not search(r'\A(#if|#ifdef|#ifndef|#else|#elif|#endif)', previous_line)): 21740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line_number -= 1; 21750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_line = clean_lines.lines[previous_line_number] 21760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_match = _RE_PATTERN_INCLUDE.search(previous_line) 21770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if previous_match: 21780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch previous_header_type = include_state.header_types[previous_line_number] 21790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if previous_header_type == _OTHER_HEADER and previous_line.strip() > line.strip(): 2180d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 21810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Alphabetical sorting problem.') 21820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if error_message: 2184d0825bca7fe65beaee391d30da42e937db621564Steve Block if file_extension == 'h': 2185d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 21860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%s Should be: alphabetically sorted.' % 21870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message) 21880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch else: 2189d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/include_order', 4, 21900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '%s Should be: config.h, primary header, blank line, and then alphabetically sorted.' % 21910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error_message) 21920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef check_language(filename, clean_lines, line_number, file_extension, include_state, 21950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error): 21960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks rules from the 'C++ language rules' section of cppguide.html. 21970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 21980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Some of these rules are hard to test (function overloading, using 21990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch uint32 inappropriately), but we do the best we can. 22000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 22020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 22030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 22040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 22050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (without the dot) of the filename. 22060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 22070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 22080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 22090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If the line is empty or consists of entirely a comment, no need to 22100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # check it. 22110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 22120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not line: 22130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 22140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(line) 22160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2217d0825bca7fe65beaee391d30da42e937db621564Steve Block check_include_line(filename, file_extension, clean_lines, line_number, include_state, error) 22180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 22190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: figure out if they're using default arguments in fn proto. 22210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check to see if they're using an conversion function cast. 22230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # I just try to capture the most common basic types, though there are more. 22240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Parameterless conversion functions, such as bool(), are allowed as they are 22250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # probably a member operator declaration or default constructor. 22260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search( 22270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) 22280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 22290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # gMock methods are defined using some variant of MOCK_METHODx(name, type) 22300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # where type may be float(), int(string), etc. Without context they are 22310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # virtually indistinguishable from int(x) casts. 22320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line): 2233d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/casting', 4, 22340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using deprecated casting style. ' 22350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Use static_cast<%s>(...) instead' % 22360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(1)) 22370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2238d0825bca7fe65beaee391d30da42e937db621564Steve Block check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number], 22390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'static_cast', 22400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'\((int|float|double|bool|char|u?int(16|32|64))\)', 22410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error) 22420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This doesn't catch all cases. Consider (const char * const)"hello". 2243d0825bca7fe65beaee391d30da42e937db621564Steve Block check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number], 22440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) 22450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # In addition, we look for people taking the address of a cast. This 22470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # is dangerous -- casts can assign to temporaries, so the pointer doesn't 22480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # point where you think. 22490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search( 22500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): 2251d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/casting', 4, 22520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('Are you taking an address of a cast? ' 22530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'This is dangerous: could be a temp var. ' 22540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Take the address before doing the cast, rather than after')) 22550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for people declaring static/global STL strings at the top level. 22570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # This is dangerous because the C++ language does not guarantee that 22580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # globals with constructors are initialized before the first access. 22590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = match( 22600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', 22610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line) 22620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Make sure it's not a function. 22630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Function template specialization looks like: "string foo<Type>(...". 22640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Class template definitions look like: "string Foo<Type>::Method(...". 22650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched and not match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', 22660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(3)): 2267d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/string', 4, 22680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'For a static/global string constant, use a C style string instead: ' 22690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '"%schar %s[]".' % 22700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (matched.group(1), matched.group(2))) 22710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check that we're not using RTTI outside of testing code. 22738a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block if search(r'\bdynamic_cast<', line): 2274d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/rtti', 5, 22750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use dynamic_cast<>. If you need to cast within a class ' 22760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "hierarchy, use static_cast<> to upcast. Google doesn't support " 22770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'RTTI.') 22780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): 2280d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/init', 4, 22810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'You seem to be initializing a member variable with itself.') 22820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if file_extension == 'h': 22840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: check that 1-arg constructors are explicit. 22850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # How to tell it's a constructor? 22860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # (handled in check_for_non_standard_constructs for now) 22870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pass 22880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if people are using the verboten C basic types. The only exception 22900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # we regularly allow is "unsigned short port" for port. 22910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bshort port\b', line): 22920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not search(r'\bunsigned short port\b', line): 2293d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/int', 4, 22940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Use "unsigned short" for ports, not "short"') 22950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 22960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # When snprintf is used, the second argument shouldn't be a literal. 22970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) 22980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2299d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 3, 23000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 23010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'to snprintf.' % (matched.group(1), matched.group(2))) 23020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check if some verboten C functions are being used. 23040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bsprintf\b', line): 2305d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 5, 23060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Never use sprintf. Use snprintf instead.') 23070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'\b(strcpy|strcat)\b', line) 23080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2309d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 4, 23100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Almost always, snprintf is better than %s' % matched.group(1)) 23110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bsscanf\b', line): 2313d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 1, 23140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'sscanf can be ok, but is slow and can overflow buffers.') 23150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for suspicious usage of "if" like 23170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # } if (a == b) { 23180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\}\s*if\s*\(', line): 2319d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/braces', 4, 23200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Did you mean "else if"? If not, start a new line for "if".') 23210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for potential format string bugs like printf(foo). 23230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We constrain the pattern not to pick things like DocidForPrintf(foo). 23240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) 23250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I) 23260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 2327d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/printf', 4, 23280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Potential format string bug. Do %s("%%s", %s) instead.' 23290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (matched.group(1), matched.group(2))) 23300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for potential memset bugs like memset(buf, sizeof(buf), 0). 23320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) 23330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched and not match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", matched.group(2)): 2334d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/memset', 4, 23350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Did you mean "memset(%s, 0, %s)"?' 23360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch % (matched.group(1), matched.group(2))) 23370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Detect variable-length arrays. 23390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) 23400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (matched and matched.group(2) != 'return' and matched.group(2) != 'delete' and 23410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched.group(3).find(']') == -1): 23420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Split the size using space and arithmetic operators as delimiters. 23430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If any of the resulting tokens are not compile time constants then 23440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # report the error. 23450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', matched.group(3)) 23460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_const = True 23470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = False 23480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for tok in tokens: 23490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if skip_next: 23500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = False 23510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'sizeof\(.+\)', tok): 23540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'arraysize\(\w+\)', tok): 23560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tok = tok.lstrip('(') 23590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch tok = tok.rstrip(')') 23600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not tok: 23610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'\d+', tok): 23630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'0[xX][0-9a-fA-F]+', tok): 23650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'k[A-Z0-9]\w*', tok): 23670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(.+::)?k[A-Z0-9]\w*', tok): 23690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): 23710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # A catch all for tricky sizeof cases, including 'sizeof expression', 23730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' 23740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # requires skipping the next token becasue we split on ' ' and '*'. 23750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if tok.startswith('sizeof'): 23760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch skip_next = True 23770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 23780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch is_const = False 23790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break 23800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not is_const: 2381d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/arrays', 1, 23820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use variable-length arrays. Use an appropriately named ' 23830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch "('k' followed by CamelCase) compile-time constant for the size.") 23840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 23850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Check for use of unnamed namespaces in header files. Registration 23860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # macros are typically OK, so we allow use of "namespace {" on lines 23870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # that end with backslashes. 23880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (file_extension == 'h' 23890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and search(r'\bnamespace\s*{', line) 23900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch and line[-1] != '\\'): 2391d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'build/namespaces', 4, 23920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Do not use unnamed namespaces in header files. See ' 23930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' 23940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ' for more information.') 23950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2396643ca7872b450ea4efacab6188849e5aac2ba161Steve Block check_identifier_name_in_declaration(filename, line_number, line, error) 2397643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2398643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2399643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdef check_identifier_name_in_declaration(filename, line_number, line, error): 2400643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """Checks if identifier names contain any underscores. 2401643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2402643ca7872b450ea4efacab6188849e5aac2ba161Steve Block As identifiers in libraries we are using have a bunch of 2403643ca7872b450ea4efacab6188849e5aac2ba161Steve Block underscores, we only warn about the declarations of identifiers 2404643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and don't check use of identifiers. 2405643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2406643ca7872b450ea4efacab6188849e5aac2ba161Steve Block Args: 2407643ca7872b450ea4efacab6188849e5aac2ba161Steve Block filename: The name of the current file. 2408643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line_number: The number of the line to check. 2409643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line: The line of code to check. 2410643ca7872b450ea4efacab6188849e5aac2ba161Steve Block error: The function to call with any errors found. 2411643ca7872b450ea4efacab6188849e5aac2ba161Steve Block """ 2412643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We don't check a return statement. 2413d0825bca7fe65beaee391d30da42e937db621564Steve Block if match(r'\s*(return|delete)\b', line): 2414643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2415643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2416643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Basically, a declaration is a type name followed by whitespaces 2417643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # followed by an identifier. The type name can be complicated 2418643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # due to type adjectives and templates. We remove them first to 2419643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # simplify the process to find declarations of identifiers. 2420643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2421643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Convert "long long", "long double", and "long long int" to 2422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # simple types, but don't remove simple "long". 2423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'long (long )?(?=long|double|int)', '', line) 2424643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'\b(unsigned|signed|inline|using|static|const|volatile|auto|register|extern|typedef|restrict|struct|class|virtual)(?=\W)', '', line) 2425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2426643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Remove all template parameters by removing matching < and >. 2427643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Loop until no templates are removed to remove nested templates. 2428643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while True: 2429643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line, number_of_replacements = subn(r'<([\w\s:]|::)+\s*[*&]*\s*>', '', line) 2430643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not number_of_replacements: 2431643ca7872b450ea4efacab6188849e5aac2ba161Steve Block break 2432643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2433643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Declarations of local variables can be in condition expressions 2434643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # of control flow statements (e.g., "if (RenderObject* p = o->parent())"). 2435643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We remove the keywords and the first parenthesis. 2436643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2437643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Declarations in "while", "if", and "switch" are different from 2438643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # other declarations in two aspects: 2439643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2440643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # - There can be only one declaration between the parentheses. 2441643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # (i.e., you cannot write "if (int i = 0, j = 1) {}") 2442643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # - The variable must be initialized. 2443643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # (i.e., you cannot write "if (int i) {}") 2444643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # 2445643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # and we will need different treatments for them. 2446643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = sub(r'^\s*for\s*\(', '', line) 2447643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line, control_statement = subn(r'^\s*(while|else if|if|switch)\s*\(', '', line) 2448643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2449643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Detect variable and functions. 2450643ca7872b450ea4efacab6188849e5aac2ba161Steve Block type_regexp = r'\w([\w]|\s*[*&]\s*|::)+' 2451643ca7872b450ea4efacab6188849e5aac2ba161Steve Block identifier_regexp = r'(?P<identifier>[\w:]+)' 2452643ca7872b450ea4efacab6188849e5aac2ba161Steve Block character_after_identifier_regexp = r'(?P<character_after_identifier>[[;()=,])(?!=)' 2453643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_without_type_regexp = r'\s*' + identifier_regexp + r'\s*' + character_after_identifier_regexp 2454643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_with_type_regexp = r'\s*' + type_regexp + r'\s' + declaration_without_type_regexp 2455643ca7872b450ea4efacab6188849e5aac2ba161Steve Block is_function_arguments = False 2456643ca7872b450ea4efacab6188849e5aac2ba161Steve Block number_of_identifiers = 0 2457643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while True: 2458643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # If we are seeing the first identifier or arguments of a 2459643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # function, there should be a type name before an identifier. 2460643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not number_of_identifiers or is_function_arguments: 2461643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_regexp = declaration_with_type_regexp 2462643ca7872b450ea4efacab6188849e5aac2ba161Steve Block else: 2463643ca7872b450ea4efacab6188849e5aac2ba161Steve Block declaration_regexp = declaration_without_type_regexp 2464643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2465643ca7872b450ea4efacab6188849e5aac2ba161Steve Block matched = match(declaration_regexp, line) 2466643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if not matched: 2467643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2468643ca7872b450ea4efacab6188849e5aac2ba161Steve Block identifier = matched.group('identifier') 2469643ca7872b450ea4efacab6188849e5aac2ba161Steve Block character_after_identifier = matched.group('character_after_identifier') 2470643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2471643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # If we removed a non-for-control statement, the character after 2472643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # the identifier should be '='. With this rule, we can avoid 2473643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # warning for cases like "if (val & INT_MAX) {". 2474643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if control_statement and character_after_identifier != '=': 2475643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2476643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2477643ca7872b450ea4efacab6188849e5aac2ba161Steve Block is_function_arguments = is_function_arguments or character_after_identifier == '(' 2478643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2479643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Remove "m_" and "s_" to allow them. 2480643ca7872b450ea4efacab6188849e5aac2ba161Steve Block modified_identifier = sub(r'(^|(?<=::))[ms]_', '', identifier) 2481643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if modified_identifier.find('_') >= 0: 2482643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Various exceptions to the rule: JavaScript op codes functions, const_iterator. 2483643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (not (filename.find('JavaScriptCore') >= 0 and modified_identifier.find('_op_') >= 0) 2484d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('tst_') 2485d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('webkit_dom_object_') 2486d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.startswith('qt_') 2487d0825bca7fe65beaee391d30da42e937db621564Steve Block and not modified_identifier.find('::qt_') >= 0 2488643ca7872b450ea4efacab6188849e5aac2ba161Steve Block and not modified_identifier == "const_iterator"): 2489d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/naming', 4, identifier + " is incorrectly named. Don't use underscores in your identifier names.") 2490643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2491643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # There can be only one declaration in non-for-control statements. 2492643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if control_statement: 2493643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2494643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # We should continue checking if this is a function 2495643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # declaration because we need to check its arguments. 2496643ca7872b450ea4efacab6188849e5aac2ba161Steve Block # Also, we need to check multiple declarations. 2497643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if character_after_identifier != '(' and character_after_identifier != ',': 2498643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return 2499643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 2500643ca7872b450ea4efacab6188849e5aac2ba161Steve Block number_of_identifiers += 1 2501643ca7872b450ea4efacab6188849e5aac2ba161Steve Block line = line[matched.end():] 2502643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 25030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2504d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef check_c_style_cast(line_number, line, raw_line, cast_type, pattern, 25050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error): 25060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Checks for a C-style cast by looking for the pattern. 25070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This also handles sizeof(type) warnings, due to similarity of content. 25090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 25110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number: The number of the line to check. 25120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: The line of code to check. 25130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_line: The raw line of code to check, with comments. 25140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch cast_type: The string for the C++ cast to recommend. This is either 25150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reinterpret_cast or static_cast, depending. 25160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch pattern: The regular expression used to find C-style casts. 25170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 25180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 25190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = search(pattern, line) 25200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not matched: 25210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 25220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # e.g., sizeof(int) 25240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch sizeof_match = match(r'.*sizeof\s*$', line[0:matched.start(1) - 1]) 25250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if sizeof_match: 2526d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'runtime/sizeof', 1, 25270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using sizeof(type). Use sizeof(varname) instead if possible') 25280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 25290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch remainder = line[matched.end(0):] 25310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The close paren is for function pointers as arguments to a function. 25330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void foo(void (*bar)(int)); 25340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The semicolon check is a more basic function check; also possibly a 25350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # function pointer typedef. 25360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void foo(int); or void foo(int) const; 25370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The equals check is for function pointer assignment. 25380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # eg, void *(*foo)(int) = ... 25390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # 25400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Right now, this will only catch cases where there's a single argument, and 25410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # it's unnamed. It should probably be expanded to check for multiple 25420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # arguments with some unnamed. 25430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_match = match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)))', remainder) 25440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if function_match: 25450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (not function_match.group(3) 25460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or function_match.group(3) == ';' 25470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch or raw_line.find('/*') < 0): 2548d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/function', 3, 25490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'All parameters should be named in a function') 25500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 25510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # At this point, all that should be left is actual casts. 2553d0825bca7fe65beaee391d30da42e937db621564Steve Block error(line_number, 'readability/casting', 4, 25540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Using C-style cast. Use %s<%s>(...) instead' % 25550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (cast_type, matched.group(1))) 25560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_HEADERS_CONTAINING_TEMPLATES = ( 25590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<deque>', ('deque',)), 25600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<functional>', ('unary_function', 'binary_function', 25610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'plus', 'minus', 'multiplies', 'divides', 'modulus', 25620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'negate', 25630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'equal_to', 'not_equal_to', 'greater', 'less', 25640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'greater_equal', 'less_equal', 25650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'logical_and', 'logical_or', 'logical_not', 25660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'unary_negate', 'not1', 'binary_negate', 'not2', 25670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'bind1st', 'bind2nd', 25680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pointer_to_unary_function', 25690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pointer_to_binary_function', 25700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'ptr_fun', 25710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', 25720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_ref_t', 25730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'const_mem_fun_t', 'const_mem_fun1_t', 25740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', 25750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'mem_fun_ref', 25760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch )), 25770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<limits>', ('numeric_limits',)), 25780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<list>', ('list',)), 25790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<map>', ('map', 'multimap',)), 25800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<memory>', ('allocator',)), 25810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<queue>', ('queue', 'priority_queue',)), 25820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<set>', ('set', 'multiset',)), 25830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<stack>', ('stack',)), 25840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<string>', ('char_traits', 'basic_string',)), 25850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<utility>', ('pair',)), 25860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<vector>', ('vector',)), 25870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # gcc extensions. 25890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Note: std::hash is their hash, ::hash is our hash 25900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<hash_map>', ('hash_map', 'hash_multimap',)), 25910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<hash_set>', ('hash_set', 'hash_multiset',)), 25920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ('<slist>', ('slist',)), 25930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ) 25940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 25950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_HEADERS_ACCEPTED_BUT_NOT_PROMOTED = { 25960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We can trust with reasonable confidence that map gives us pair<>, too. 25970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'pair<>': ('map', 'multimap', 'hash_map', 'hash_multimap') 25980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 25990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_RE_PATTERN_STRING = re.compile(r'\bstring\b') 26010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_re_pattern_algorithm_header = [] 26030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', 26040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'transform'): 26050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Match max<type>(..., ...), max(..., ...), but not foo->max, foo.max or 26060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # type::max(). 26070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _re_pattern_algorithm_header.append( 26080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), 26090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _template, 26100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '<algorithm>')) 26110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch_re_pattern_templates = [] 26130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfor _header, _templates in _HEADERS_CONTAINING_TEMPLATES: 26140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for _template in _templates: 26150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _re_pattern_templates.append( 26160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (re.compile(r'(\<|\b)' + _template + r'\s*\<'), 26170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _template + '<>', 26180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch _header)) 26190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef files_belong_to_same_module(filename_cpp, filename_h): 26220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Check if these two filenames belong to the same module. 26230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch The concept of a 'module' here is a as follows: 26250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch foo.h, foo-inl.h, foo.cpp, foo_test.cpp and foo_unittest.cpp belong to the 26260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch same 'module' if they are in the same directory. 26270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch some/path/public/xyzzy and some/path/internal/xyzzy are also considered 26280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch to belong to the same module here. 26290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch If the filename_cpp contains a longer path than the filename_h, for example, 26310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch '/absolute/path/to/base/sysinfo.cpp', and this file would include 26320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'base/sysinfo.h', this function also produces the prefix needed to open the 26330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header. This is used by the caller of this function to more robustly open the 26340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header file. We don't have access to the real include paths in this context, 26350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch so we need this guesswork here. 26360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Known bugs: tools/base/bar.cpp and base/bar.h belong to the same module 26380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch according to this implementation. Because of this, this function gives 26390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch some false positives. This should be sufficiently rare in practice. 26400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 26420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp: is the path for the .cpp file 26430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h: is the path for the header path 26440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 26460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Tuple with a bool and a string: 26470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch bool: True if filename_cpp and filename_h belong to the same module. 26480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch string: the additional prefix needed to open the header file. 26490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 26500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not filename_cpp.endswith('.cpp'): 26520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (False, '') 26530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('.cpp')] 26540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename_cpp.endswith('_unittest'): 26550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('_unittest')] 26560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch elif filename_cpp.endswith('_test'): 26570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp[:-len('_test')] 26580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp.replace('/public/', '/') 26590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_cpp = filename_cpp.replace('/internal/', '/') 26600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not filename_h.endswith('.h'): 26620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return (False, '') 26630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h[:-len('.h')] 26640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename_h.endswith('-inl'): 26650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h[:-len('-inl')] 26660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h.replace('/public/', '/') 26670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename_h = filename_h.replace('/internal/', '/') 26680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch files_belong_to_same_module = filename_cpp.endswith(filename_h) 26700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch common_path = '' 26710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if files_belong_to_same_module: 26720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch common_path = filename_cpp[:-len(filename_h)] 26730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return files_belong_to_same_module, common_path 26740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef update_include_state(filename, include_state, io=codecs): 26770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Fill up the include_state with new includes found from the file. 26780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 26800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: the name of the header to read. 26810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: an _IncludeState instance in which the headers are inserted. 26820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch io: The io factory to use to read the file. Provided for testability. 26830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 26840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Returns: 26850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch True if a header was succesfully added. False otherwise. 26860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 26870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_file = None 26880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch try: 26890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_file = io.open(filename, 'r', 'utf8', 'replace') 26900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch except IOError: 26910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return False 26920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number = 0 26930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in header_file: 26940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line_number += 1 26950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_line = cleanse_comments(line) 26960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch matched = _RE_PATTERN_INCLUDE.search(clean_line) 26970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if matched: 26980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include = matched.group(2) 26990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The value formatting is cute, but not really used right now. 27000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # What matters here is that the key is in include_state. 27010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state.setdefault(include, '%s:%d' % (filename, line_number)) 27020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return True 27030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef check_for_include_what_you_use(filename, clean_lines, include_state, error, 27060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch io=codecs): 27070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Reports for missing stl includes. 27080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch This function will output warnings to make sure you are including the headers 27100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch necessary for the stl containers and functions that you use. We only give one 27110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reason to include a header. For example, if you use both equal_to<> and 27120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch less<> in a .h file, only one (the latter in the file) of these will be 27130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch reported as a reason to include the <functional>. 27140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 27160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: The name of the current file. 27170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: A CleansedLines instance containing the file. 27180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance. 27190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: The function to call with any errors found. 27200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch io: The IO factory to use to read the header file. Provided for unittest 27210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch injection. 27220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 27230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required = {} # A map of header name to line_number and the template entity. 27240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Example of required: { '<functional>': (1219, 'less<>') } 27250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line_number in xrange(clean_lines.num_lines()): 27270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line = clean_lines.elided[line_number] 27280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not line or line[0] == '#': 27290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 27300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # String is special -- it is a non-templatized type in STL. 27320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if _RE_PATTERN_STRING.search(line): 27330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required['<string>'] = (line_number, 'string') 27340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern, template, header in _re_pattern_algorithm_header: 27360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if pattern.search(line): 27370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required[header] = (line_number, template) 27380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The following function is just a speed up, no semantics are changed. 27400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if not '<' in line: # Reduces the cpu time usage by skipping lines. 27410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 27420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for pattern, template, header in _re_pattern_templates: 27440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if pattern.search(line): 27450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch required[header] = (line_number, template) 27460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # The policy is that if you #include something in foo.h you don't need to 27480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include it again in foo.cpp. Here, we will look at possible includes. 27490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Let's copy the include_state so it is only messed up within this function. 27500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state = include_state.copy() 27510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Did we find the header for this file (if any) and succesfully load it? 27530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_found = False 27540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # Use the absolute path so that matching works properly. 27560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch abs_filename = os.path.abspath(filename) 27570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # For Emacs's flymake. 27590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If cpp_style is invoked from Emacs's flymake, a temporary file is generated 27600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # by flymake and that file name might end with '_flymake.cpp'. In that case, 27610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # restore original file name here so that the corresponding header file can be 27620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # found. 27630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # e.g. If the file name is 'foo_flymake.cpp', we should search for 'foo.h' 27640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # instead of 'foo_flymake.h' 27650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch emacs_flymake_suffix = '_flymake.cpp' 27660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if abs_filename.endswith(emacs_flymake_suffix): 27670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch abs_filename = abs_filename[:-len(emacs_flymake_suffix)] + '.cpp' 27680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # include_state is modified during iteration, so we iterate over a copy of 27700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # the keys. 27710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for header in include_state.keys(): #NOLINT 27720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch (same_module, common_path) = files_belong_to_same_module(abs_filename, header) 27730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch fullpath = common_path + header 27740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if same_module and update_include_state(fullpath, include_state, io): 27750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch header_found = True 27760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # If we can't find the header file for a .cpp, assume it's because we don't 27780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # know where to look. In that case we'll give up as we're not sure they 27790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # didn't include it in the .h file. 27800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # FIXME: Do a better job of finding .h files so we are confident that 27810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # not having the .h file means there isn't one. 27820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if filename.endswith('.cpp') and not header_found: 27830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 27840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # All the lines have been processed, report the errors found. 27860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for required_header_unstripped in required: 27870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch template = required[required_header_unstripped][1] 27880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if template in _HEADERS_ACCEPTED_BUT_NOT_PROMOTED: 27890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch headers = _HEADERS_ACCEPTED_BUT_NOT_PROMOTED[template] 27900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if [True for header in headers if header in include_state]: 27910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch continue 27920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if required_header_unstripped.strip('<>"') not in include_state: 2793d0825bca7fe65beaee391d30da42e937db621564Steve Block error(required[required_header_unstripped][0], 27940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'build/include_what_you_use', 4, 27950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 'Add #include ' + required_header_unstripped + ' for ' + template) 27960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 27980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochdef process_line(filename, file_extension, 27990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines, line, include_state, function_state, 2800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block class_state, file_state, error): 28010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Processes a single line in the file. 28020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 28040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: Filename of the file that is being processed. 28050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 28060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines: An array of strings, each representing a line of the file, 28070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch with comments stripped. 28080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch line: Number of line being processed. 28090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state: An _IncludeState instance in which the headers are inserted. 28100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch function_state: A _FunctionState instance which counts function lines, etc. 28110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state: A _ClassState instance which maintains information about 28120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch the current stack of nested class declarations being parsed. 2813643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state: A _FileState instance which maintains information about 2814643ca7872b450ea4efacab6188849e5aac2ba161Steve Block the state of things in the file. 2815d0825bca7fe65beaee391d30da42e937db621564Steve Block error: A callable to which errors are reported, which takes arguments: 2816d0825bca7fe65beaee391d30da42e937db621564Steve Block line number, error level, and message 28170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 28190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch raw_lines = clean_lines.raw_lines 2820d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_function_lengths(clean_lines, line, function_state, error) 28210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if search(r'\bNOLINT\b', raw_lines[line]): # ignore nolint lines 28220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return 2823d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_multiline_comments_and_strings(clean_lines, line, error) 2824d0825bca7fe65beaee391d30da42e937db621564Steve Block check_style(clean_lines, line, file_extension, file_state, error) 28250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_language(filename, clean_lines, line, file_extension, include_state, 28260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error) 2827d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_non_standard_constructs(clean_lines, line, class_state, error) 2828d0825bca7fe65beaee391d30da42e937db621564Steve Block check_posix_threading(clean_lines, line, error) 2829d0825bca7fe65beaee391d30da42e937db621564Steve Block check_invalid_increment(clean_lines, line, error) 28300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2832d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef _process_lines(filename, file_extension, lines, error, verbosity): 28330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """Performs lint checks and reports any errors to the given error function. 28340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch Args: 28360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch filename: Filename of the file that is being processed. 28370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch file_extension: The extension (dot not included) of the file. 28380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines: An array of strings, each representing a line of the file, with the 28390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch last element being empty if the file is termined with a newline. 28400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch error: A callable to which errors are reported, which takes 4 arguments: 28410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch """ 28420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch lines = (['// marker so line numbers and indices both start at 1'] + lines + 28430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ['// marker so line numbers end in a known way']) 28440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch include_state = _IncludeState() 2846d0825bca7fe65beaee391d30da42e937db621564Steve Block function_state = _FunctionState(verbosity) 28470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch class_state = _ClassState() 2848643ca7872b450ea4efacab6188849e5aac2ba161Steve Block file_state = _FileState() 28490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2850d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_copyright(lines, error) 28510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if file_extension == 'h': 28530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_for_header_guard(filename, lines, error) 28540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2855d0825bca7fe65beaee391d30da42e937db621564Steve Block remove_multi_line_comments(lines, error) 28560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch clean_lines = CleansedLines(lines) 28570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch for line in xrange(clean_lines.num_lines()): 28580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch process_line(filename, file_extension, clean_lines, line, 2859643ca7872b450ea4efacab6188849e5aac2ba161Steve Block include_state, function_state, class_state, file_state, error) 2860d0825bca7fe65beaee391d30da42e937db621564Steve Block class_state.check_finished(error) 28610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch check_for_include_what_you_use(filename, clean_lines, include_state, error) 28630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # We check here rather than inside process_line so that we see raw 28650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch # lines rather than "cleaned" lines. 2866d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_unicode_replacement_characters(lines, error) 28670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2868d0825bca7fe65beaee391d30da42e937db621564Steve Block check_for_new_line_at_eof(lines, error) 28690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 28700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2871d0825bca7fe65beaee391d30da42e937db621564Steve Blockclass CppProcessor(object): 28720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2873d0825bca7fe65beaee391d30da42e937db621564Steve Block """Processes C++ lines for checking style.""" 28740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2875d0825bca7fe65beaee391d30da42e937db621564Steve Block # This list is used to-- 2876d0825bca7fe65beaee391d30da42e937db621564Steve Block # 2877d0825bca7fe65beaee391d30da42e937db621564Steve Block # (1) generate an explicit list of all possible categories, 2878d0825bca7fe65beaee391d30da42e937db621564Steve Block # (2) unit test that all checked categories have valid names, and 2879d0825bca7fe65beaee391d30da42e937db621564Steve Block # (3) unit test that all categories are getting unit tested. 2880d0825bca7fe65beaee391d30da42e937db621564Steve Block # 2881d0825bca7fe65beaee391d30da42e937db621564Steve Block categories = set([ 2882d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/class', 2883d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/deprecated', 2884d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/endif_comment', 2885d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/forward_decl', 2886d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/header_guard', 2887d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include', 2888d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include_order', 2889d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/include_what_you_use', 2890d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/namespaces', 2891d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/printf_format', 2892d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/storage_class', 2893d0825bca7fe65beaee391d30da42e937db621564Steve Block 'build/using_std', 2894d0825bca7fe65beaee391d30da42e937db621564Steve Block 'legal/copyright', 2895d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/braces', 2896d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/casting', 2897d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/check', 2898d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/comparison_to_zero', 2899d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/constructors', 2900d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/control_flow', 2901d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/fn_size', 2902d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/function', 2903d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/multiline_comment', 2904d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/multiline_string', 2905d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/naming', 2906d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/null', 2907d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/streams', 2908d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/todo', 2909d0825bca7fe65beaee391d30da42e937db621564Steve Block 'readability/utf8', 2910d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/arrays', 2911d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/casting', 2912d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/explicit', 2913d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/init', 2914d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/int', 2915d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/invalid_increment', 2916d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/max_min_macros', 2917d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/memset', 2918d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/printf', 2919d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/printf_format', 2920d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/references', 2921d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/rtti', 2922d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/sizeof', 2923d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/string', 2924d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/threadsafe_fn', 2925d0825bca7fe65beaee391d30da42e937db621564Steve Block 'runtime/virtual', 2926d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/blank_line', 2927d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/braces', 2928d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/comma', 2929d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/comments', 2930d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/declaration', 2931d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/end_of_line', 2932d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/ending_newline', 2933d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/indent', 2934d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/labels', 2935d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/line_length', 2936d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/newline', 2937d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/operators', 2938d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/parens', 2939d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/semicolon', 2940d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/tab', 2941d0825bca7fe65beaee391d30da42e937db621564Steve Block 'whitespace/todo', 2942d0825bca7fe65beaee391d30da42e937db621564Steve Block ]) 2943d0825bca7fe65beaee391d30da42e937db621564Steve Block 2944d0825bca7fe65beaee391d30da42e937db621564Steve Block def __init__(self, file_path, file_extension, handle_style_error, verbosity): 2945d0825bca7fe65beaee391d30da42e937db621564Steve Block """Create a CppProcessor instance. 29460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2947d0825bca7fe65beaee391d30da42e937db621564Steve Block Args: 2948d0825bca7fe65beaee391d30da42e937db621564Steve Block file_extension: A string that is the file extension, without 2949d0825bca7fe65beaee391d30da42e937db621564Steve Block the leading dot. 29500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2951d0825bca7fe65beaee391d30da42e937db621564Steve Block """ 2952d0825bca7fe65beaee391d30da42e937db621564Steve Block self.file_extension = file_extension 2953d0825bca7fe65beaee391d30da42e937db621564Steve Block self.file_path = file_path 2954d0825bca7fe65beaee391d30da42e937db621564Steve Block self.handle_style_error = handle_style_error 2955d0825bca7fe65beaee391d30da42e937db621564Steve Block self.verbosity = verbosity 2956d0825bca7fe65beaee391d30da42e937db621564Steve Block 2957d0825bca7fe65beaee391d30da42e937db621564Steve Block # Useful for unit testing. 2958d0825bca7fe65beaee391d30da42e937db621564Steve Block def __eq__(self, other): 2959d0825bca7fe65beaee391d30da42e937db621564Steve Block """Return whether this CppProcessor instance is equal to another.""" 2960d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.file_extension != other.file_extension: 2961d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 2962d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.file_path != other.file_path: 2963d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 2964d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.handle_style_error != other.handle_style_error: 2965d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 2966d0825bca7fe65beaee391d30da42e937db621564Steve Block if self.verbosity != other.verbosity: 2967d0825bca7fe65beaee391d30da42e937db621564Steve Block return False 29680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2969d0825bca7fe65beaee391d30da42e937db621564Steve Block return True 29700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2971d0825bca7fe65beaee391d30da42e937db621564Steve Block # Useful for unit testing. 2972d0825bca7fe65beaee391d30da42e937db621564Steve Block def __ne__(self, other): 2973d0825bca7fe65beaee391d30da42e937db621564Steve Block # Python does not automatically deduce __ne__() from __eq__(). 2974d0825bca7fe65beaee391d30da42e937db621564Steve Block return not self.__eq__(other) 29750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2976d0825bca7fe65beaee391d30da42e937db621564Steve Block def process(self, lines): 2977d0825bca7fe65beaee391d30da42e937db621564Steve Block _process_lines(self.file_path, self.file_extension, lines, 2978d0825bca7fe65beaee391d30da42e937db621564Steve Block self.handle_style_error, self.verbosity) 29790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 29800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2981d0825bca7fe65beaee391d30da42e937db621564Steve Block# FIXME: Remove this function (requires refactoring unit tests). 2982d0825bca7fe65beaee391d30da42e937db621564Steve Blockdef process_file_data(filename, file_extension, lines, error, verbosity): 2983d0825bca7fe65beaee391d30da42e937db621564Steve Block processor = CppProcessor(filename, file_extension, error, verbosity) 2984d0825bca7fe65beaee391d30da42e937db621564Steve Block processor.process(lines) 29850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2986