mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Update cpplint.py to #242:
- Check indentation of public/protected/private keywords. - Remove RTTI warning. - Silence warning about multiple inheritance from global namespace. - Copy ctors don't need "explicit". - Understand "const char* const&" as a const reference. - Remove runtime/sizeof. - Recognize the "catch" keyword. - List C++11 headers - Allow sscanf() - Allow for one extra level of nesting in template class decls. - False positive for semicolons after single-line nameless unions. R=mark@chromium.org Review URL: https://codereview.appspot.com/15740044
This commit is contained in:
parent
7b24563e08
commit
fd5da63478
391
cpplint/cpplint.py
vendored
391
cpplint/cpplint.py
vendored
|
@ -200,8 +200,6 @@ _ERROR_CATEGORIES = [
|
||||||
'runtime/printf',
|
'runtime/printf',
|
||||||
'runtime/printf_format',
|
'runtime/printf_format',
|
||||||
'runtime/references',
|
'runtime/references',
|
||||||
'runtime/rtti',
|
|
||||||
'runtime/sizeof',
|
|
||||||
'runtime/string',
|
'runtime/string',
|
||||||
'runtime/threadsafe_fn',
|
'runtime/threadsafe_fn',
|
||||||
'whitespace/blank_line',
|
'whitespace/blank_line',
|
||||||
|
@ -213,7 +211,6 @@ _ERROR_CATEGORIES = [
|
||||||
'whitespace/ending_newline',
|
'whitespace/ending_newline',
|
||||||
'whitespace/forcolon',
|
'whitespace/forcolon',
|
||||||
'whitespace/indent',
|
'whitespace/indent',
|
||||||
'whitespace/labels',
|
|
||||||
'whitespace/line_length',
|
'whitespace/line_length',
|
||||||
'whitespace/newline',
|
'whitespace/newline',
|
||||||
'whitespace/operators',
|
'whitespace/operators',
|
||||||
|
@ -233,36 +230,143 @@ _DEFAULT_FILTERS = ['-build/include_alpha']
|
||||||
# decided those were OK, as long as they were in UTF-8 and didn't represent
|
# decided those were OK, as long as they were in UTF-8 and didn't represent
|
||||||
# hard-coded international strings, which belong in a separate i18n file.
|
# hard-coded international strings, which belong in a separate i18n file.
|
||||||
|
|
||||||
# Headers that we consider STL headers.
|
|
||||||
_STL_HEADERS = frozenset([
|
|
||||||
'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception',
|
|
||||||
'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set',
|
|
||||||
'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new',
|
|
||||||
'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack',
|
|
||||||
'stl_alloc.h', 'stl_relops.h', 'type_traits.h',
|
|
||||||
'utility', 'vector', 'vector.h',
|
|
||||||
])
|
|
||||||
|
|
||||||
|
# C++ headers
|
||||||
# Non-STL C++ system headers.
|
|
||||||
_CPP_HEADERS = frozenset([
|
_CPP_HEADERS = frozenset([
|
||||||
'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype',
|
# Legacy
|
||||||
'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath',
|
'algobase.h',
|
||||||
'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef',
|
'algo.h',
|
||||||
'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype',
|
'alloc.h',
|
||||||
'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream',
|
'builtinbuf.h',
|
||||||
'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip',
|
'bvector.h',
|
||||||
'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream',
|
'complex.h',
|
||||||
'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h',
|
'defalloc.h',
|
||||||
'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h',
|
'deque.h',
|
||||||
'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h',
|
'editbuf.h',
|
||||||
'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept',
|
'fstream.h',
|
||||||
'stdiostream.h', 'streambuf', 'streambuf.h', 'stream.h', 'strfile.h',
|
'function.h',
|
||||||
'string', 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo',
|
'hash_map',
|
||||||
|
'hash_map.h',
|
||||||
|
'hash_set',
|
||||||
|
'hash_set.h',
|
||||||
|
'hashtable.h',
|
||||||
|
'heap.h',
|
||||||
|
'indstream.h',
|
||||||
|
'iomanip.h',
|
||||||
|
'iostream.h',
|
||||||
|
'istream.h',
|
||||||
|
'iterator.h',
|
||||||
|
'list.h',
|
||||||
|
'map.h',
|
||||||
|
'multimap.h',
|
||||||
|
'multiset.h',
|
||||||
|
'ostream.h',
|
||||||
|
'pair.h',
|
||||||
|
'parsestream.h',
|
||||||
|
'pfstream.h',
|
||||||
|
'procbuf.h',
|
||||||
|
'pthread_alloc',
|
||||||
|
'pthread_alloc.h',
|
||||||
|
'rope',
|
||||||
|
'rope.h',
|
||||||
|
'ropeimpl.h',
|
||||||
|
'set.h',
|
||||||
|
'slist',
|
||||||
|
'slist.h',
|
||||||
|
'stack.h',
|
||||||
|
'stdiostream.h',
|
||||||
|
'stl_alloc.h',
|
||||||
|
'stl_relops.h',
|
||||||
|
'streambuf.h',
|
||||||
|
'stream.h',
|
||||||
|
'strfile.h',
|
||||||
|
'strstream.h',
|
||||||
|
'tempbuf.h',
|
||||||
|
'tree.h',
|
||||||
|
'type_traits.h',
|
||||||
|
'vector.h',
|
||||||
|
# 17.6.1.2 C++ library headers
|
||||||
|
'algorithm',
|
||||||
|
'array',
|
||||||
|
'atomic',
|
||||||
|
'bitset',
|
||||||
|
'chrono',
|
||||||
|
'codecvt',
|
||||||
|
'complex',
|
||||||
|
'condition_variable',
|
||||||
|
'deque',
|
||||||
|
'exception',
|
||||||
|
'forward_list',
|
||||||
|
'fstream',
|
||||||
|
'functional',
|
||||||
|
'future',
|
||||||
|
'initializer_list',
|
||||||
|
'iomanip',
|
||||||
|
'ios',
|
||||||
|
'iosfwd',
|
||||||
|
'iostream',
|
||||||
|
'istream',
|
||||||
|
'iterator',
|
||||||
|
'limits',
|
||||||
|
'list',
|
||||||
|
'locale',
|
||||||
|
'map',
|
||||||
|
'memory',
|
||||||
|
'mutex',
|
||||||
|
'new',
|
||||||
|
'numeric',
|
||||||
|
'ostream',
|
||||||
|
'queue',
|
||||||
|
'random',
|
||||||
|
'ratio',
|
||||||
|
'regex',
|
||||||
|
'set',
|
||||||
|
'sstream',
|
||||||
|
'stack',
|
||||||
|
'stdexcept',
|
||||||
|
'streambuf',
|
||||||
|
'string',
|
||||||
|
'strstream',
|
||||||
|
'system_error',
|
||||||
|
'thread',
|
||||||
|
'tuple',
|
||||||
|
'typeindex',
|
||||||
|
'typeinfo',
|
||||||
|
'type_traits',
|
||||||
|
'unordered_map',
|
||||||
|
'unordered_set',
|
||||||
|
'utility',
|
||||||
'valarray',
|
'valarray',
|
||||||
|
'vector',
|
||||||
|
# 17.6.1.2 C++ headers for C library facilities
|
||||||
|
'cassert',
|
||||||
|
'ccomplex',
|
||||||
|
'cctype',
|
||||||
|
'cerrno',
|
||||||
|
'cfenv',
|
||||||
|
'cfloat',
|
||||||
|
'cinttypes',
|
||||||
|
'ciso646',
|
||||||
|
'climits',
|
||||||
|
'clocale',
|
||||||
|
'cmath',
|
||||||
|
'csetjmp',
|
||||||
|
'csignal',
|
||||||
|
'cstdalign',
|
||||||
|
'cstdarg',
|
||||||
|
'cstdbool',
|
||||||
|
'cstddef',
|
||||||
|
'cstdint',
|
||||||
|
'cstdio',
|
||||||
|
'cstdlib',
|
||||||
|
'cstring',
|
||||||
|
'ctgmath',
|
||||||
|
'ctime',
|
||||||
|
'cuchar',
|
||||||
|
'cwchar',
|
||||||
|
'cwctype',
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
# Assertion macros. These are defined in base/logging.h and
|
# Assertion macros. These are defined in base/logging.h and
|
||||||
# testing/base/gunit.h. Note that the _M versions need to come first
|
# testing/base/gunit.h. Note that the _M versions need to come first
|
||||||
# for substring matching to work.
|
# for substring matching to work.
|
||||||
|
@ -416,6 +520,24 @@ def Match(pattern, s):
|
||||||
return _regexp_compile_cache[pattern].match(s)
|
return _regexp_compile_cache[pattern].match(s)
|
||||||
|
|
||||||
|
|
||||||
|
def ReplaceAll(pattern, rep, s):
|
||||||
|
"""Replaces instances of pattern in a string with a replacement.
|
||||||
|
|
||||||
|
The compiled regex is kept in a cache shared by Match and Search.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern: regex pattern
|
||||||
|
rep: replacement text
|
||||||
|
s: search string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string with replacements made (or original string if no replacements)
|
||||||
|
"""
|
||||||
|
if pattern not in _regexp_compile_cache:
|
||||||
|
_regexp_compile_cache[pattern] = sre_compile.compile(pattern)
|
||||||
|
return _regexp_compile_cache[pattern].sub(rep, s)
|
||||||
|
|
||||||
|
|
||||||
def Search(pattern, s):
|
def Search(pattern, s):
|
||||||
"""Searches the string for the pattern, caching the compiled regexp."""
|
"""Searches the string for the pattern, caching the compiled regexp."""
|
||||||
if not pattern in _regexp_compile_cache:
|
if not pattern in _regexp_compile_cache:
|
||||||
|
@ -464,6 +586,9 @@ class _IncludeState(dict):
|
||||||
# The path of last found header.
|
# The path of last found header.
|
||||||
self._last_header = ''
|
self._last_header = ''
|
||||||
|
|
||||||
|
def SetLastHeader(self, header_path):
|
||||||
|
self._last_header = header_path
|
||||||
|
|
||||||
def CanonicalizeAlphabeticalOrder(self, header_path):
|
def CanonicalizeAlphabeticalOrder(self, header_path):
|
||||||
"""Returns a path canonicalized for alphabetical comparison.
|
"""Returns a path canonicalized for alphabetical comparison.
|
||||||
|
|
||||||
|
@ -479,19 +604,25 @@ class _IncludeState(dict):
|
||||||
"""
|
"""
|
||||||
return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
|
return header_path.replace('-inl.h', '.h').replace('-', '_').lower()
|
||||||
|
|
||||||
def IsInAlphabeticalOrder(self, header_path):
|
def IsInAlphabeticalOrder(self, clean_lines, linenum, header_path):
|
||||||
"""Check if a header is in alphabetical order with the previous header.
|
"""Check if a header is in alphabetical order with the previous header.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
header_path: Header to be checked.
|
clean_lines: A CleansedLines instance containing the file.
|
||||||
|
linenum: The number of the line to check.
|
||||||
|
header_path: Canonicalized header to be checked.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Returns true if the header is in alphabetical order.
|
Returns true if the header is in alphabetical order.
|
||||||
"""
|
"""
|
||||||
canonical_header = self.CanonicalizeAlphabeticalOrder(header_path)
|
# If previous section is different from current section, _last_header will
|
||||||
if self._last_header > canonical_header:
|
# be reset to empty string, so it's always less than current header.
|
||||||
|
#
|
||||||
|
# If previous line was a blank line, assume that the headers are
|
||||||
|
# intentionally sorted the way they are.
|
||||||
|
if (self._last_header > header_path and
|
||||||
|
not Match(r'^\s*$', clean_lines.elided[linenum - 1])):
|
||||||
return False
|
return False
|
||||||
self._last_header = canonical_header
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def CheckNextIncludeOrder(self, header_type):
|
def CheckNextIncludeOrder(self, header_type):
|
||||||
|
@ -1401,8 +1532,18 @@ class _ClassInfo(_BlockInfo):
|
||||||
self.is_derived = False
|
self.is_derived = False
|
||||||
if class_or_struct == 'struct':
|
if class_or_struct == 'struct':
|
||||||
self.access = 'public'
|
self.access = 'public'
|
||||||
|
self.is_struct = True
|
||||||
else:
|
else:
|
||||||
self.access = 'private'
|
self.access = 'private'
|
||||||
|
self.is_struct = False
|
||||||
|
|
||||||
|
# Remember initial indentation level for this class. Using raw_lines here
|
||||||
|
# instead of elided to account for leading comments like http://go/abjhm
|
||||||
|
initial_indent = Match(r'^( *)\S', clean_lines.raw_lines[linenum])
|
||||||
|
if initial_indent:
|
||||||
|
self.class_indent = len(initial_indent.group(1))
|
||||||
|
else:
|
||||||
|
self.class_indent = 0
|
||||||
|
|
||||||
# Try to find the end of the class. This will be confused by things like:
|
# Try to find the end of the class. This will be confused by things like:
|
||||||
# class A {
|
# class A {
|
||||||
|
@ -1423,6 +1564,19 @@ class _ClassInfo(_BlockInfo):
|
||||||
if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
|
if Search('(^|[^:]):($|[^:])', clean_lines.elided[linenum]):
|
||||||
self.is_derived = True
|
self.is_derived = True
|
||||||
|
|
||||||
|
def CheckEnd(self, filename, clean_lines, linenum, error):
|
||||||
|
# Check that closing brace is aligned with beginning of the class.
|
||||||
|
# Only do this if the closing brace is indented by only whitespaces.
|
||||||
|
# This means we will not check single-line class definitions.
|
||||||
|
indent = Match(r'^( *)\}', clean_lines.elided[linenum])
|
||||||
|
if indent and len(indent.group(1)) != self.class_indent:
|
||||||
|
if self.is_struct:
|
||||||
|
parent = 'struct ' + self.name
|
||||||
|
else:
|
||||||
|
parent = 'class ' + self.name
|
||||||
|
error(filename, linenum, 'whitespace/indent', 3,
|
||||||
|
'Closing brace should be aligned with beginning of %s' % parent)
|
||||||
|
|
||||||
|
|
||||||
class _NamespaceInfo(_BlockInfo):
|
class _NamespaceInfo(_BlockInfo):
|
||||||
"""Stores information about a namespace."""
|
"""Stores information about a namespace."""
|
||||||
|
@ -1661,8 +1815,8 @@ class _NestingState(object):
|
||||||
# To avoid these cases, we ignore classes that are followed by '=' or '>'
|
# To avoid these cases, we ignore classes that are followed by '=' or '>'
|
||||||
class_decl_match = Match(
|
class_decl_match = Match(
|
||||||
r'\s*(template\s*<[\w\s<>,:]*>\s*)?'
|
r'\s*(template\s*<[\w\s<>,:]*>\s*)?'
|
||||||
'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)'
|
r'(class|struct)\s+([A-Z_]+\s+)*(\w+(?:::\w+)*)'
|
||||||
'(([^=>]|<[^<>]*>)*)$', line)
|
r'(([^=>]|<[^<>]*>|<[^<>]*<[^<>]*>\s*>)*)$', line)
|
||||||
if (class_decl_match and
|
if (class_decl_match and
|
||||||
(not self.stack or self.stack[-1].open_parentheses == 0)):
|
(not self.stack or self.stack[-1].open_parentheses == 0)):
|
||||||
self.stack.append(_ClassInfo(
|
self.stack.append(_ClassInfo(
|
||||||
|
@ -1677,9 +1831,30 @@ class _NestingState(object):
|
||||||
|
|
||||||
# Update access control if we are inside a class/struct
|
# Update access control if we are inside a class/struct
|
||||||
if self.stack and isinstance(self.stack[-1], _ClassInfo):
|
if self.stack and isinstance(self.stack[-1], _ClassInfo):
|
||||||
access_match = Match(r'\s*(public|private|protected)\s*:', line)
|
classinfo = self.stack[-1]
|
||||||
|
access_match = Match(
|
||||||
|
r'^(.*)\b(public|private|protected|signals)(\s+(?:slots\s*)?)?'
|
||||||
|
r':(?:[^:]|$)',
|
||||||
|
line)
|
||||||
if access_match:
|
if access_match:
|
||||||
self.stack[-1].access = access_match.group(1)
|
classinfo.access = access_match.group(2)
|
||||||
|
|
||||||
|
# Check that access keywords are indented +1 space. Skip this
|
||||||
|
# check if the keywords are not preceded by whitespaces, examples:
|
||||||
|
# http://go/cfudb + http://go/vxnkk
|
||||||
|
indent = access_match.group(1)
|
||||||
|
if (len(indent) != classinfo.class_indent + 1 and
|
||||||
|
Match(r'^\s*$', indent)):
|
||||||
|
if classinfo.is_struct:
|
||||||
|
parent = 'struct ' + classinfo.name
|
||||||
|
else:
|
||||||
|
parent = 'class ' + classinfo.name
|
||||||
|
slots = ''
|
||||||
|
if access_match.group(3):
|
||||||
|
slots = access_match.group(3)
|
||||||
|
error(filename, linenum, 'whitespace/indent', 3,
|
||||||
|
'%s%s: should be indented +1 space inside %s' % (
|
||||||
|
access_match.group(2), slots, parent))
|
||||||
|
|
||||||
# Consume braces or semicolons from what's left of the line
|
# Consume braces or semicolons from what's left of the line
|
||||||
while True:
|
while True:
|
||||||
|
@ -1848,8 +2023,8 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
|
||||||
line)
|
line)
|
||||||
if (args and
|
if (args and
|
||||||
args.group(1) != 'void' and
|
args.group(1) != 'void' and
|
||||||
not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname),
|
not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&'
|
||||||
args.group(1).strip())):
|
% re.escape(base_classname), args.group(1).strip())):
|
||||||
error(filename, linenum, 'runtime/explicit', 5,
|
error(filename, linenum, 'runtime/explicit', 5,
|
||||||
'Single-argument constructors should be marked explicit.')
|
'Single-argument constructors should be marked explicit.')
|
||||||
|
|
||||||
|
@ -1892,7 +2067,7 @@ def CheckSpacingForFunctionCall(filename, line, linenum, error):
|
||||||
# Note that we assume the contents of [] to be short enough that
|
# Note that we assume the contents of [] to be short enough that
|
||||||
# they'll never need to wrap.
|
# they'll never need to wrap.
|
||||||
if ( # Ignore control structures.
|
if ( # Ignore control structures.
|
||||||
not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and
|
not Search(r'\b(if|for|while|switch|return|delete|catch)\b', fncall) and
|
||||||
# Ignore pointers/references to functions.
|
# Ignore pointers/references to functions.
|
||||||
not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
|
not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and
|
||||||
# Ignore pointers/references to arrays.
|
# Ignore pointers/references to arrays.
|
||||||
|
@ -2635,7 +2810,7 @@ def CheckBraces(filename, clean_lines, linenum, error):
|
||||||
break
|
break
|
||||||
if (Search(r'{.*}\s*;', line) and
|
if (Search(r'{.*}\s*;', line) and
|
||||||
line.count('{') == line.count('}') and
|
line.count('{') == line.count('}') and
|
||||||
not Search(r'struct|class|enum|\s*=\s*{', line)):
|
not Search(r'struct|union|class|enum|\s*=\s*{', line)):
|
||||||
error(filename, linenum, 'readability/braces', 4,
|
error(filename, linenum, 'readability/braces', 4,
|
||||||
"You don't need a ; after a }")
|
"You don't need a ; after a }")
|
||||||
|
|
||||||
|
@ -2833,21 +3008,12 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
|
||||||
if line and line[-1].isspace():
|
if line and line[-1].isspace():
|
||||||
error(filename, linenum, 'whitespace/end_of_line', 4,
|
error(filename, linenum, 'whitespace/end_of_line', 4,
|
||||||
'Line ends in whitespace. Consider deleting these extra spaces.')
|
'Line ends in whitespace. Consider deleting these extra spaces.')
|
||||||
# There are certain situations we allow one space, notably for labels
|
# There are certain situations we allow one space, notably for section labels
|
||||||
elif ((initial_spaces == 1 or initial_spaces == 3) and
|
elif ((initial_spaces == 1 or initial_spaces == 3) and
|
||||||
not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
|
not Match(r'\s*\w+\s*:\s*$', cleansed_line)):
|
||||||
error(filename, linenum, 'whitespace/indent', 3,
|
error(filename, linenum, 'whitespace/indent', 3,
|
||||||
'Weird number of spaces at line-start. '
|
'Weird number of spaces at line-start. '
|
||||||
'Are you using a 2-space indent?')
|
'Are you using a 2-space indent?')
|
||||||
# Labels should always be indented at least one space.
|
|
||||||
elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$',
|
|
||||||
line):
|
|
||||||
error(filename, linenum, 'whitespace/labels', 4,
|
|
||||||
'Labels should always be indented at least one space. '
|
|
||||||
'If this is a member-initializer list in a constructor or '
|
|
||||||
'the base class list in a class definition, the colon should '
|
|
||||||
'be on the following line.')
|
|
||||||
|
|
||||||
|
|
||||||
# Check if the line is a header guard.
|
# Check if the line is a header guard.
|
||||||
is_header_guard = False
|
is_header_guard = False
|
||||||
|
@ -2980,8 +3146,7 @@ def _ClassifyInclude(fileinfo, include, is_system):
|
||||||
"""
|
"""
|
||||||
# This is a list of all standard c++ header files, except
|
# This is a list of all standard c++ header files, except
|
||||||
# those already checked for above.
|
# those already checked for above.
|
||||||
is_stl_h = include in _STL_HEADERS
|
is_cpp_h = include in _CPP_HEADERS
|
||||||
is_cpp_h = is_stl_h or include in _CPP_HEADERS
|
|
||||||
|
|
||||||
if is_system:
|
if is_system:
|
||||||
if is_cpp_h:
|
if is_cpp_h:
|
||||||
|
@ -3069,9 +3234,12 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
|
||||||
error(filename, linenum, 'build/include_order', 4,
|
error(filename, linenum, 'build/include_order', 4,
|
||||||
'%s. Should be: %s.h, c system, c++ system, other.' %
|
'%s. Should be: %s.h, c system, c++ system, other.' %
|
||||||
(error_message, fileinfo.BaseName()))
|
(error_message, fileinfo.BaseName()))
|
||||||
if not include_state.IsInAlphabeticalOrder(include):
|
canonical_include = include_state.CanonicalizeAlphabeticalOrder(include)
|
||||||
|
if not include_state.IsInAlphabeticalOrder(
|
||||||
|
clean_lines, linenum, canonical_include):
|
||||||
error(filename, linenum, 'build/include_alpha', 4,
|
error(filename, linenum, 'build/include_alpha', 4,
|
||||||
'Include "%s" not in alphabetical order' % include)
|
'Include "%s" not in alphabetical order' % include)
|
||||||
|
include_state.SetLastHeader(canonical_include)
|
||||||
|
|
||||||
# Look for any of the stream classes that are part of standard C++.
|
# Look for any of the stream classes that are part of standard C++.
|
||||||
match = _RE_PATTERN_INCLUDE.match(line)
|
match = _RE_PATTERN_INCLUDE.match(line)
|
||||||
|
@ -3140,8 +3308,24 @@ def _GetTextInside(text, start_pattern):
|
||||||
return text[start_position:position - 1]
|
return text[start_position:position - 1]
|
||||||
|
|
||||||
|
|
||||||
def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
|
# Patterns for matching call-by-reference parameters.
|
||||||
error):
|
_RE_PATTERN_IDENT = r'[_a-zA-Z]\w*' # =~ [[:alpha:]][[:alnum:]]*
|
||||||
|
_RE_PATTERN_TYPE = (
|
||||||
|
r'(?:const\s+)?(?:typename\s+|class\s+|struct\s+|union\s+|enum\s+)?'
|
||||||
|
r'[\w:]*\w(?:\s*<[\w:*, ]*>(?:::\w+)?)?')
|
||||||
|
# A call-by-reference parameter ends with '& identifier'.
|
||||||
|
_RE_PATTERN_REF_PARAM = re.compile(
|
||||||
|
r'(' + _RE_PATTERN_TYPE + r'(?:\s*(?:\bconst\b|[*]))*\s*'
|
||||||
|
r'&\s*' + _RE_PATTERN_IDENT + r')\s*(?:=[^,()]+)?[,)]')
|
||||||
|
# A call-by-const-reference parameter either ends with 'const& identifier'
|
||||||
|
# or looks like 'const type& identifier' when 'type' is atomic.
|
||||||
|
_RE_PATTERN_CONST_REF_PARAM = (
|
||||||
|
r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
|
||||||
|
r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
|
||||||
|
|
||||||
|
|
||||||
|
def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
||||||
|
include_state, nesting_state, error):
|
||||||
"""Checks rules from the 'C++ language rules' section of cppguide.html.
|
"""Checks rules from the 'C++ language rules' section of cppguide.html.
|
||||||
|
|
||||||
Some of these rules are hard to test (function overloading, using
|
Some of these rules are hard to test (function overloading, using
|
||||||
|
@ -3153,6 +3337,8 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
|
||||||
linenum: The number of the line to check.
|
linenum: The number of the line to check.
|
||||||
file_extension: The extension (without the dot) of the filename.
|
file_extension: The extension (without the dot) of the filename.
|
||||||
include_state: An _IncludeState instance in which the headers are inserted.
|
include_state: An _IncludeState instance in which the headers are inserted.
|
||||||
|
nesting_state: A _NestingState instance which maintains information about
|
||||||
|
the current stack of nested blocks being parsed.
|
||||||
error: The function to call with any errors found.
|
error: The function to call with any errors found.
|
||||||
"""
|
"""
|
||||||
# If the line is empty or consists of entirely a comment, no need to
|
# If the line is empty or consists of entirely a comment, no need to
|
||||||
|
@ -3179,30 +3365,56 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
|
||||||
|
|
||||||
# TODO(unknown): figure out if they're using default arguments in fn proto.
|
# TODO(unknown): figure out if they're using default arguments in fn proto.
|
||||||
|
|
||||||
# Check for non-const references in functions. This is tricky because &
|
# Check for non-const references in function parameters. A single '&' may
|
||||||
# is also used to take the address of something. We allow <> for templates,
|
# found in the following places:
|
||||||
# (ignoring whatever is between the braces) and : for classes.
|
# inside expression: binary & for bitwise AND
|
||||||
# These are complicated re's. They try to capture the following:
|
# inside expression: unary & for taking the address of something
|
||||||
# paren (for fn-prototype start), typename, &, varname. For the const
|
# inside declarators: reference parameter
|
||||||
# version, we're willing for const to be before typename or after
|
# We will exclude the first two cases by checking that we are not inside a
|
||||||
# Don't check the implementation on same line.
|
# function body, including one that was just introduced by a trailing '{'.
|
||||||
fnline = line.split('{', 1)[0]
|
# TODO(unknown): Doesn't account for preprocessor directives.
|
||||||
if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) >
|
# TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
|
||||||
len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?'
|
# TODO(unknown): Doesn't account for line breaks within declarators.
|
||||||
r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) +
|
check_params = False
|
||||||
len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+',
|
if not nesting_state.stack:
|
||||||
fnline))):
|
check_params = True # top level
|
||||||
|
elif (isinstance(nesting_state.stack[-1], _ClassInfo) or
|
||||||
|
isinstance(nesting_state.stack[-1], _NamespaceInfo)):
|
||||||
|
check_params = True # within class or namespace
|
||||||
|
elif Match(r'.*{\s*$', line):
|
||||||
|
if (len(nesting_state.stack) == 1 or
|
||||||
|
isinstance(nesting_state.stack[-2], _ClassInfo) or
|
||||||
|
isinstance(nesting_state.stack[-2], _NamespaceInfo)):
|
||||||
|
check_params = True # just opened global/class/namespace block
|
||||||
|
# We allow non-const references in a few standard places, like functions
|
||||||
|
# called "swap()" or iostream operators like "<<" or ">>". Do not check
|
||||||
|
# those function parameters.
|
||||||
|
#
|
||||||
|
# We also accept & in static_assert, which looks like a function but
|
||||||
|
# it's actually a declaration expression.
|
||||||
|
whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
|
||||||
|
r'operator\s*[<>][<>]|'
|
||||||
|
r'static_assert|COMPILE_ASSERT'
|
||||||
|
r')\s*\(')
|
||||||
|
if Search(whitelisted_functions, line):
|
||||||
|
check_params = False
|
||||||
|
elif not Search(r'\S+\([^)]*$', line):
|
||||||
|
# Don't see a whitelisted function on this line. Actually we
|
||||||
|
# didn't see any function name on this line, so this is likely a
|
||||||
|
# multi-line parameter list. Try a bit harder to catch this case.
|
||||||
|
for i in xrange(2):
|
||||||
|
if (linenum > i and
|
||||||
|
Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
|
||||||
|
check_params = False
|
||||||
|
break
|
||||||
|
|
||||||
# We allow non-const references in a few standard places, like functions
|
if check_params:
|
||||||
# called "swap()" or iostream operators like "<<" or ">>". We also filter
|
decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
|
||||||
# out for loops, which lint otherwise mistakenly thinks are functions.
|
for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
|
||||||
if not Search(
|
if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
|
||||||
r'(for|swap|Swap|operator[<>][<>])\s*\(\s*'
|
error(filename, linenum, 'runtime/references', 2,
|
||||||
r'(?:(?:typename\s*)?[\w:]|<.*>)+\s*&',
|
'Is this a non-const reference? '
|
||||||
fnline):
|
'If so, make const or use a pointer: ' + parameter)
|
||||||
error(filename, linenum, 'runtime/references', 2,
|
|
||||||
'Is this a non-const reference? '
|
|
||||||
'If so, make const or use a pointer.')
|
|
||||||
|
|
||||||
# Check to see if they're using an conversion function cast.
|
# Check to see if they're using an conversion function cast.
|
||||||
# I just try to capture the most common basic types, though there are more.
|
# I just try to capture the most common basic types, though there are more.
|
||||||
|
@ -3276,13 +3488,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
|
||||||
'"%schar %s[]".' %
|
'"%schar %s[]".' %
|
||||||
(match.group(1), match.group(2)))
|
(match.group(1), match.group(2)))
|
||||||
|
|
||||||
# Check that we're not using RTTI outside of testing code.
|
|
||||||
if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename):
|
|
||||||
error(filename, linenum, 'runtime/rtti', 5,
|
|
||||||
'Do not use dynamic_cast<>. If you need to cast within a class '
|
|
||||||
"hierarchy, use static_cast<> to upcast. Google doesn't support "
|
|
||||||
'RTTI.')
|
|
||||||
|
|
||||||
if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
|
if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
|
||||||
error(filename, linenum, 'runtime/init', 4,
|
error(filename, linenum, 'runtime/init', 4,
|
||||||
'You seem to be initializing a member variable with itself.')
|
'You seem to be initializing a member variable with itself.')
|
||||||
|
@ -3324,10 +3529,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state,
|
||||||
error(filename, linenum, 'runtime/printf', 4,
|
error(filename, linenum, 'runtime/printf', 4,
|
||||||
'Almost always, snprintf is better than %s' % match.group(1))
|
'Almost always, snprintf is better than %s' % match.group(1))
|
||||||
|
|
||||||
if Search(r'\bsscanf\b', line):
|
|
||||||
error(filename, linenum, 'runtime/printf', 1,
|
|
||||||
'sscanf can be ok, but is slow and can overflow buffers.')
|
|
||||||
|
|
||||||
# Check if some verboten operator overloading is going on
|
# Check if some verboten operator overloading is going on
|
||||||
# TODO(unknown): catch out-of-line unary operator&:
|
# TODO(unknown): catch out-of-line unary operator&:
|
||||||
# class X {};
|
# class X {};
|
||||||
|
@ -3448,8 +3649,6 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
|
||||||
error):
|
error):
|
||||||
"""Checks for a C-style cast by looking for the pattern.
|
"""Checks for a C-style cast by looking for the pattern.
|
||||||
|
|
||||||
This also handles sizeof(type) warnings, due to similarity of content.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filename: The name of the current file.
|
filename: The name of the current file.
|
||||||
linenum: The number of the line to check.
|
linenum: The number of the line to check.
|
||||||
|
@ -3468,12 +3667,10 @@ def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern,
|
||||||
if not match:
|
if not match:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# e.g., sizeof(int)
|
# Exclude lines with sizeof, since sizeof looks like a cast.
|
||||||
sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
|
sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1])
|
||||||
if sizeof_match:
|
if sizeof_match:
|
||||||
error(filename, linenum, 'runtime/sizeof', 1,
|
return False
|
||||||
'Using sizeof(type). Use sizeof(varname) instead if possible')
|
|
||||||
return True
|
|
||||||
|
|
||||||
# operator++(int) and operator--(int)
|
# operator++(int) and operator--(int)
|
||||||
if (line[0:match.start(1) - 1].endswith(' operator++') or
|
if (line[0:match.start(1) - 1].endswith(' operator++') or
|
||||||
|
@ -3802,7 +3999,7 @@ def ProcessLine(filename, file_extension, clean_lines, line,
|
||||||
CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
|
CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error)
|
||||||
CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
|
CheckStyle(filename, clean_lines, line, file_extension, nesting_state, error)
|
||||||
CheckLanguage(filename, clean_lines, line, file_extension, include_state,
|
CheckLanguage(filename, clean_lines, line, file_extension, include_state,
|
||||||
error)
|
nesting_state, error)
|
||||||
CheckForNonStandardConstructs(filename, clean_lines, line,
|
CheckForNonStandardConstructs(filename, clean_lines, line,
|
||||||
nesting_state, error)
|
nesting_state, error)
|
||||||
CheckPosixThreading(filename, clean_lines, line, error)
|
CheckPosixThreading(filename, clean_lines, line, error)
|
||||||
|
|
|
@ -147,13 +147,14 @@ class CpplintTestBase(unittest.TestCase):
|
||||||
def PerformLanguageRulesCheck(self, file_name, code):
|
def PerformLanguageRulesCheck(self, file_name, code):
|
||||||
error_collector = ErrorCollector(self.assert_)
|
error_collector = ErrorCollector(self.assert_)
|
||||||
include_state = cpplint._IncludeState()
|
include_state = cpplint._IncludeState()
|
||||||
|
nesting_state = cpplint._NestingState()
|
||||||
lines = code.split('\n')
|
lines = code.split('\n')
|
||||||
cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
|
cpplint.RemoveMultiLineComments(file_name, lines, error_collector)
|
||||||
lines = cpplint.CleansedLines(lines)
|
lines = cpplint.CleansedLines(lines)
|
||||||
ext = file_name[file_name.rfind('.') + 1:]
|
ext = file_name[file_name.rfind('.') + 1:]
|
||||||
for i in xrange(lines.NumLines()):
|
for i in xrange(lines.NumLines()):
|
||||||
cpplint.CheckLanguage(file_name, lines, i, ext, include_state,
|
cpplint.CheckLanguage(file_name, lines, i, ext, include_state,
|
||||||
error_collector)
|
nesting_state, error_collector)
|
||||||
return error_collector.Results()
|
return error_collector.Results()
|
||||||
|
|
||||||
def PerformFunctionLengthsCheck(self, code):
|
def PerformFunctionLengthsCheck(self, code):
|
||||||
|
@ -186,12 +187,13 @@ class CpplintTestBase(unittest.TestCase):
|
||||||
# First, build up the include state.
|
# First, build up the include state.
|
||||||
error_collector = ErrorCollector(self.assert_)
|
error_collector = ErrorCollector(self.assert_)
|
||||||
include_state = cpplint._IncludeState()
|
include_state = cpplint._IncludeState()
|
||||||
|
nesting_state = cpplint._NestingState()
|
||||||
lines = code.split('\n')
|
lines = code.split('\n')
|
||||||
cpplint.RemoveMultiLineComments(filename, lines, error_collector)
|
cpplint.RemoveMultiLineComments(filename, lines, error_collector)
|
||||||
lines = cpplint.CleansedLines(lines)
|
lines = cpplint.CleansedLines(lines)
|
||||||
for i in xrange(lines.NumLines()):
|
for i in xrange(lines.NumLines()):
|
||||||
cpplint.CheckLanguage(filename, lines, i, '.h', include_state,
|
cpplint.CheckLanguage(filename, lines, i, '.h', include_state,
|
||||||
error_collector)
|
nesting_state, error_collector)
|
||||||
# We could clear the error_collector here, but this should
|
# We could clear the error_collector here, but this should
|
||||||
# also be fine, since our IncludeWhatYouUse unittests do not
|
# also be fine, since our IncludeWhatYouUse unittests do not
|
||||||
# have language problems.
|
# have language problems.
|
||||||
|
@ -410,16 +412,6 @@ class CpplintTest(CpplintTestBase):
|
||||||
'Take the address before doing the cast, rather than after'
|
'Take the address before doing the cast, rather than after'
|
||||||
' [runtime/casting] [4]')
|
' [runtime/casting] [4]')
|
||||||
|
|
||||||
self.TestLint(
|
|
||||||
'int* x = &dynamic_cast<int *>(foo);',
|
|
||||||
['Are you taking an address of a cast? '
|
|
||||||
'This is dangerous: could be a temp var. '
|
|
||||||
'Take the address before doing the cast, rather than after'
|
|
||||||
' [runtime/casting] [4]',
|
|
||||||
'Do not use dynamic_cast<>. If you need to cast within a class '
|
|
||||||
'hierarchy, use static_cast<> to upcast. Google doesn\'t support '
|
|
||||||
'RTTI. [runtime/rtti] [5]'])
|
|
||||||
|
|
||||||
self.TestLint(
|
self.TestLint(
|
||||||
'int* x = &reinterpret_cast<int *>(foo);',
|
'int* x = &reinterpret_cast<int *>(foo);',
|
||||||
'Are you taking an address of a cast? '
|
'Are you taking an address of a cast? '
|
||||||
|
@ -444,20 +436,6 @@ class CpplintTest(CpplintTestBase):
|
||||||
'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }',
|
'Foo::Foo(Bar r) : r_(r), l_(r_), ll_(l_) { }',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
def testRuntimeRTTI(self):
|
|
||||||
statement = 'int* x = dynamic_cast<int*>(&foo);'
|
|
||||||
error_message = (
|
|
||||||
'Do not use dynamic_cast<>. If you need to cast within a class '
|
|
||||||
'hierarchy, use static_cast<> to upcast. Google doesn\'t support '
|
|
||||||
'RTTI. [runtime/rtti] [5]')
|
|
||||||
# dynamic_cast is disallowed in most files.
|
|
||||||
self.TestLanguageRulesCheck('foo.cc', statement, error_message)
|
|
||||||
self.TestLanguageRulesCheck('foo.h', statement, error_message)
|
|
||||||
# It is explicitly allowed in tests, however.
|
|
||||||
self.TestLanguageRulesCheck('foo_test.cc', statement, '')
|
|
||||||
self.TestLanguageRulesCheck('foo_unittest.cc', statement, '')
|
|
||||||
self.TestLanguageRulesCheck('foo_regtest.cc', statement, '')
|
|
||||||
|
|
||||||
# Test for unnamed arguments in a method.
|
# Test for unnamed arguments in a method.
|
||||||
def testCheckForUnnamedParams(self):
|
def testCheckForUnnamedParams(self):
|
||||||
message = ('All parameters should be named in a function'
|
message = ('All parameters should be named in a function'
|
||||||
|
@ -571,17 +549,6 @@ class CpplintTest(CpplintTestBase):
|
||||||
'MockCallback<int(float, char)>',
|
'MockCallback<int(float, char)>',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
# Test sizeof(type) cases.
|
|
||||||
def testSizeofType(self):
|
|
||||||
self.TestLint(
|
|
||||||
'sizeof(int);',
|
|
||||||
'Using sizeof(type). Use sizeof(varname) instead if possible'
|
|
||||||
' [runtime/sizeof] [1]')
|
|
||||||
self.TestLint(
|
|
||||||
'sizeof(int *);',
|
|
||||||
'Using sizeof(type). Use sizeof(varname) instead if possible'
|
|
||||||
' [runtime/sizeof] [1]')
|
|
||||||
|
|
||||||
# Test false errors that happened with some include file names
|
# Test false errors that happened with some include file names
|
||||||
def testIncludeFilenameFalseError(self):
|
def testIncludeFilenameFalseError(self):
|
||||||
self.TestLint(
|
self.TestLint(
|
||||||
|
@ -876,111 +843,127 @@ class CpplintTest(CpplintTestBase):
|
||||||
def testExplicitSingleArgumentConstructors(self):
|
def testExplicitSingleArgumentConstructors(self):
|
||||||
# missing explicit is bad
|
# missing explicit is bad
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(int f);
|
class Foo {
|
||||||
};""",
|
Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# missing explicit is bad, even with whitespace
|
# missing explicit is bad, even with whitespace
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo (int f);
|
class Foo {
|
||||||
};""",
|
Foo (int f);
|
||||||
|
};""",
|
||||||
['Extra space before ( in function call [whitespace/parens] [4]',
|
['Extra space before ( in function call [whitespace/parens] [4]',
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]'])
|
' [runtime/explicit] [5]'])
|
||||||
# missing explicit, with distracting comment, is still bad
|
# missing explicit, with distracting comment, is still bad
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(int f); // simpler than Foo(blargh, blarg)
|
class Foo {
|
||||||
};""",
|
Foo(int f); // simpler than Foo(blargh, blarg)
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# missing explicit, with qualified classname
|
# missing explicit, with qualified classname
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Qualifier::AnotherOne::Foo {
|
"""
|
||||||
Foo(int f);
|
class Qualifier::AnotherOne::Foo {
|
||||||
};""",
|
Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# missing explicit for inline constructors is bad as well
|
# missing explicit for inline constructors is bad as well
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
inline Foo(int f);
|
class Foo {
|
||||||
};""",
|
inline Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# structs are caught as well.
|
# structs are caught as well.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""struct Foo {
|
"""
|
||||||
Foo(int f);
|
struct Foo {
|
||||||
};""",
|
Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# Templatized classes are caught as well.
|
# Templatized classes are caught as well.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""template<typename T> class Foo {
|
"""
|
||||||
Foo(int f);
|
template<typename T> class Foo {
|
||||||
};""",
|
Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# inline case for templatized classes.
|
# inline case for templatized classes.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""template<typename T> class Foo {
|
"""
|
||||||
inline Foo(int f);
|
template<typename T> class Foo {
|
||||||
};""",
|
inline Foo(int f);
|
||||||
|
};""",
|
||||||
'Single-argument constructors should be marked explicit.'
|
'Single-argument constructors should be marked explicit.'
|
||||||
' [runtime/explicit] [5]')
|
' [runtime/explicit] [5]')
|
||||||
# proper style is okay
|
# proper style is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
explicit Foo(int f);
|
class Foo {
|
||||||
};""",
|
explicit Foo(int f);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# two argument constructor is okay
|
# two argument constructor is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(int f, int b);
|
class Foo {
|
||||||
};""",
|
Foo(int f, int b);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# two argument constructor, across two lines, is okay
|
# two argument constructor, across two lines, is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(int f,
|
class Foo {
|
||||||
int b);
|
Foo(int f,
|
||||||
};""",
|
int b);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# non-constructor (but similar name), is okay
|
# non-constructor (but similar name), is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
aFoo(int f);
|
class Foo {
|
||||||
};""",
|
aFoo(int f);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# constructor with void argument is okay
|
# constructor with void argument is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(void);
|
class Foo {
|
||||||
};""",
|
Foo(void);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# single argument method is okay
|
# single argument method is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Bar(int b);
|
class Foo {
|
||||||
};""",
|
Bar(int b);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# comments should be ignored
|
# comments should be ignored
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
// Foo(int f);
|
class Foo {
|
||||||
};""",
|
// Foo(int f);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# single argument function following class definition is okay
|
# single argument function following class definition is okay
|
||||||
# (okay, it's not actually valid, but we don't want a false positive)
|
# (okay, it's not actually valid, but we don't want a false positive)
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(int f, int b);
|
class Foo {
|
||||||
};
|
Foo(int f, int b);
|
||||||
Foo(int f);""",
|
};
|
||||||
|
Foo(int f);""",
|
||||||
'')
|
'')
|
||||||
# single argument function is okay
|
# single argument function is okay
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
|
@ -988,20 +971,29 @@ class CpplintTest(CpplintTestBase):
|
||||||
'')
|
'')
|
||||||
# single argument copy constructor is okay.
|
# single argument copy constructor is okay.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(const Foo&);
|
class Foo {
|
||||||
};""",
|
Foo(const Foo&);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo {
|
"""
|
||||||
Foo(Foo&);
|
class Foo {
|
||||||
};""",
|
Foo(Foo const&);
|
||||||
|
};""",
|
||||||
|
'')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
class Foo {
|
||||||
|
Foo(Foo&);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# templatized copy constructor is okay.
|
# templatized copy constructor is okay.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""template<typename T> class Foo {
|
"""
|
||||||
Foo(const Foo<T>&);
|
template<typename T> class Foo {
|
||||||
};""",
|
Foo(const Foo<T>&);
|
||||||
|
};""",
|
||||||
'')
|
'')
|
||||||
# Anything goes inside an assembly block
|
# Anything goes inside an assembly block
|
||||||
error_collector = ErrorCollector(self.assert_)
|
error_collector = ErrorCollector(self.assert_)
|
||||||
|
@ -1267,7 +1259,8 @@ class CpplintTest(CpplintTestBase):
|
||||||
'DISALLOW_COPY_AND_ASSIGN',
|
'DISALLOW_COPY_AND_ASSIGN',
|
||||||
'DISALLOW_IMPLICIT_CONSTRUCTORS'):
|
'DISALLOW_IMPLICIT_CONSTRUCTORS'):
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class A {'
|
"""
|
||||||
|
class A {'
|
||||||
public:
|
public:
|
||||||
%s(A);
|
%s(A);
|
||||||
};""" % macro_name,
|
};""" % macro_name,
|
||||||
|
@ -1275,14 +1268,16 @@ class CpplintTest(CpplintTestBase):
|
||||||
' [readability/constructors] [3]')
|
' [readability/constructors] [3]')
|
||||||
|
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""struct B {'
|
"""
|
||||||
|
struct B {'
|
||||||
%s(B);
|
%s(B);
|
||||||
};""" % macro_name,
|
};""" % macro_name,
|
||||||
('%s must be in the private: section' % macro_name) +
|
('%s must be in the private: section' % macro_name) +
|
||||||
' [readability/constructors] [3]')
|
' [readability/constructors] [3]')
|
||||||
|
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Outer1 {'
|
"""
|
||||||
|
class Outer1 {'
|
||||||
private:
|
private:
|
||||||
struct Inner1 {
|
struct Inner1 {
|
||||||
%s(Inner1);
|
%s(Inner1);
|
||||||
|
@ -1293,7 +1288,8 @@ class CpplintTest(CpplintTestBase):
|
||||||
' [readability/constructors] [3]')
|
' [readability/constructors] [3]')
|
||||||
|
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Outer2 {'
|
"""
|
||||||
|
class Outer2 {'
|
||||||
private:
|
private:
|
||||||
class Inner2 {
|
class Inner2 {
|
||||||
%s(Inner2);
|
%s(Inner2);
|
||||||
|
@ -1305,7 +1301,8 @@ class CpplintTest(CpplintTestBase):
|
||||||
# correctly. Use different macros for inner and outer classes so
|
# correctly. Use different macros for inner and outer classes so
|
||||||
# that we can tell the error messages apart.
|
# that we can tell the error messages apart.
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Outer3 {
|
"""
|
||||||
|
class Outer3 {
|
||||||
struct Inner3 {
|
struct Inner3 {
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(Inner3);
|
DISALLOW_EVIL_CONSTRUCTORS(Inner3);
|
||||||
};
|
};
|
||||||
|
@ -1314,7 +1311,8 @@ class CpplintTest(CpplintTestBase):
|
||||||
('DISALLOW_EVIL_CONSTRUCTORS must be in the private: section'
|
('DISALLOW_EVIL_CONSTRUCTORS must be in the private: section'
|
||||||
' [readability/constructors] [3]'))
|
' [readability/constructors] [3]'))
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""struct Outer4 {
|
"""
|
||||||
|
struct Outer4 {
|
||||||
class Inner4 {
|
class Inner4 {
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(Inner4);
|
DISALLOW_EVIL_CONSTRUCTORS(Inner4);
|
||||||
};
|
};
|
||||||
|
@ -1527,12 +1525,16 @@ class CpplintTest(CpplintTestBase):
|
||||||
def testNonConstReference(self):
|
def testNonConstReference(self):
|
||||||
# Passing a non-const reference as function parameter is forbidden.
|
# Passing a non-const reference as function parameter is forbidden.
|
||||||
operand_error_message = ('Is this a non-const reference? '
|
operand_error_message = ('Is this a non-const reference? '
|
||||||
'If so, make const or use a pointer.'
|
'If so, make const or use a pointer: %s'
|
||||||
' [runtime/references] [2]')
|
' [runtime/references] [2]')
|
||||||
# Warn of use of a non-const reference in operators and functions
|
# Warn of use of a non-const reference in operators and functions
|
||||||
self.TestLint('bool operator>(Foo& s, Foo& f);', operand_error_message)
|
self.TestLint('bool operator>(Foo& s, Foo& f);',
|
||||||
self.TestLint('bool operator+(Foo& s, Foo& f);', operand_error_message)
|
[operand_error_message % 'Foo& s',
|
||||||
self.TestLint('int len(Foo& s);', operand_error_message)
|
operand_error_message % 'Foo& f'])
|
||||||
|
self.TestLint('bool operator+(Foo& s, Foo& f);',
|
||||||
|
[operand_error_message % 'Foo& s',
|
||||||
|
operand_error_message % 'Foo& f'])
|
||||||
|
self.TestLint('int len(Foo& s);', operand_error_message % 'Foo& s')
|
||||||
# Allow use of non-const references in a few specific cases
|
# Allow use of non-const references in a few specific cases
|
||||||
self.TestLint('stream& operator>>(stream& s, Foo& f);', '')
|
self.TestLint('stream& operator>>(stream& s, Foo& f);', '')
|
||||||
self.TestLint('stream& operator<<(stream& s, Foo& f);', '')
|
self.TestLint('stream& operator<<(stream& s, Foo& f);', '')
|
||||||
|
@ -1543,6 +1545,28 @@ class CpplintTest(CpplintTestBase):
|
||||||
self.TestLint('void foo(const struct tm& tm);', '')
|
self.TestLint('void foo(const struct tm& tm);', '')
|
||||||
# Passing a const reference to a typename is OK.
|
# Passing a const reference to a typename is OK.
|
||||||
self.TestLint('void foo(const typename tm& tm);', '')
|
self.TestLint('void foo(const typename tm& tm);', '')
|
||||||
|
# Const reference to a pointer type is OK.
|
||||||
|
self.TestLint('void foo(const Bar* const& p) {', '')
|
||||||
|
self.TestLint('void foo(Bar const* const& p) {', '')
|
||||||
|
self.TestLint('void foo(Bar* const& p) {', '')
|
||||||
|
# Const reference to a templated type is OK.
|
||||||
|
self.TestLint('void foo(const std::vector<std::string>& v);', '')
|
||||||
|
# Non-const reference to a pointer type is not OK.
|
||||||
|
self.TestLint('void foo(Bar*& p);',
|
||||||
|
operand_error_message % 'Bar*& p')
|
||||||
|
self.TestLint('void foo(const Bar*& p);',
|
||||||
|
operand_error_message % 'const Bar*& p')
|
||||||
|
self.TestLint('void foo(Bar const*& p);',
|
||||||
|
operand_error_message % 'Bar const*& p')
|
||||||
|
self.TestLint('void foo(struct Bar*& p);',
|
||||||
|
operand_error_message % 'struct Bar*& p')
|
||||||
|
self.TestLint('void foo(const struct Bar*& p);',
|
||||||
|
operand_error_message % 'const struct Bar*& p')
|
||||||
|
self.TestLint('void foo(struct Bar const*& p);',
|
||||||
|
operand_error_message % 'struct Bar const*& p')
|
||||||
|
# Non-const reference to a templated type is not OK.
|
||||||
|
self.TestLint('void foo(std::vector<int>& p);',
|
||||||
|
operand_error_message % 'std::vector<int>& p')
|
||||||
# Returning an address of something is not prohibited.
|
# Returning an address of something is not prohibited.
|
||||||
self.TestLint('return &something;', '')
|
self.TestLint('return &something;', '')
|
||||||
self.TestLint('if (condition) {return &something; }', '')
|
self.TestLint('if (condition) {return &something; }', '')
|
||||||
|
@ -1556,6 +1580,34 @@ class CpplintTest(CpplintTestBase):
|
||||||
self.TestLint('for (const string& s : c)', '')
|
self.TestLint('for (const string& s : c)', '')
|
||||||
self.TestLint('for (auto& r : c)', '')
|
self.TestLint('for (auto& r : c)', '')
|
||||||
self.TestLint('for (typename Type& a : b)', '')
|
self.TestLint('for (typename Type& a : b)', '')
|
||||||
|
# We don't get confused by some other uses of '&'.
|
||||||
|
self.TestLint('T& operator=(const T& t);', '')
|
||||||
|
self.TestLint('int g() { return (a & b); }', '')
|
||||||
|
self.TestLint('T& r = (T&)*(vp());', '')
|
||||||
|
self.TestLint('T& r = v', '')
|
||||||
|
self.TestLint('static_assert((kBits & kMask) == 0, "text");', '')
|
||||||
|
self.TestLint('COMPILE_ASSERT((kBits & kMask) == 0, text);', '')
|
||||||
|
|
||||||
|
# Another potential false positive. This one needs full parser
|
||||||
|
# state to reproduce as opposed to just TestLint.
|
||||||
|
error_collector = ErrorCollector(self.assert_)
|
||||||
|
cpplint.ProcessFileData(
|
||||||
|
'foo.cc', 'cc',
|
||||||
|
['// Copyright 2008 Your Company. All Rights Reserved.',
|
||||||
|
'void swap(int &x,',
|
||||||
|
' int &y) {',
|
||||||
|
'}',
|
||||||
|
'void swap(',
|
||||||
|
' sparsegroup<T, GROUP_SIZE, Alloc> &x,',
|
||||||
|
' sparsegroup<T, GROUP_SIZE, Alloc> &y) {',
|
||||||
|
'}',
|
||||||
|
'ostream& operator<<(',
|
||||||
|
' ostream& out',
|
||||||
|
' const dense_hash_set<Value, Hash, Equals, Alloc>& seq) {',
|
||||||
|
'}',
|
||||||
|
''],
|
||||||
|
error_collector)
|
||||||
|
self.assertEquals('', error_collector.Results())
|
||||||
|
|
||||||
def testBraceAtBeginOfLine(self):
|
def testBraceAtBeginOfLine(self):
|
||||||
self.TestLint('{',
|
self.TestLint('{',
|
||||||
|
@ -1628,6 +1680,7 @@ class CpplintTest(CpplintTestBase):
|
||||||
self.TestLint('((a+b))', '')
|
self.TestLint('((a+b))', '')
|
||||||
self.TestLint('foo (foo)', 'Extra space before ( in function call'
|
self.TestLint('foo (foo)', 'Extra space before ( in function call'
|
||||||
' [whitespace/parens] [4]')
|
' [whitespace/parens] [4]')
|
||||||
|
self.TestLint('} catch (const Foo& ex) {', '')
|
||||||
self.TestLint('typedef foo (*foo)(foo)', '')
|
self.TestLint('typedef foo (*foo)(foo)', '')
|
||||||
self.TestLint('typedef foo (*foo12bar_)(foo)', '')
|
self.TestLint('typedef foo (*foo12bar_)(foo)', '')
|
||||||
self.TestLint('typedef foo (Foo::*bar)(foo)', '')
|
self.TestLint('typedef foo (Foo::*bar)(foo)', '')
|
||||||
|
@ -1652,6 +1705,15 @@ class CpplintTest(CpplintTestBase):
|
||||||
self.TestLint('for {', '')
|
self.TestLint('for {', '')
|
||||||
self.TestLint('EXPECT_DEBUG_DEATH({', '')
|
self.TestLint('EXPECT_DEBUG_DEATH({', '')
|
||||||
|
|
||||||
|
def testSemiColonAfterBraces(self):
|
||||||
|
self.TestLint('if (cond) {};',
|
||||||
|
'You don\'t need a ; after a } [readability/braces] [4]')
|
||||||
|
self.TestLint('class X {};', '')
|
||||||
|
self.TestLint('struct X {};', '')
|
||||||
|
self.TestLint('union {} x;', '')
|
||||||
|
self.TestLint('union {};', '')
|
||||||
|
self.TestLint('union {};', '')
|
||||||
|
|
||||||
def testSpacingAroundElse(self):
|
def testSpacingAroundElse(self):
|
||||||
self.TestLint('}else {', 'Missing space before else'
|
self.TestLint('}else {', 'Missing space before else'
|
||||||
' [whitespace/braces] [5]')
|
' [whitespace/braces] [5]')
|
||||||
|
@ -2211,24 +2273,76 @@ class CpplintTest(CpplintTestBase):
|
||||||
self.TestLint(' char* one_space_indent = "public:";',
|
self.TestLint(' char* one_space_indent = "public:";',
|
||||||
'Weird number of spaces at line-start. '
|
'Weird number of spaces at line-start. '
|
||||||
'Are you using a 2-space indent? [whitespace/indent] [3]')
|
'Are you using a 2-space indent? [whitespace/indent] [3]')
|
||||||
self.TestLint(' public:', '')
|
|
||||||
self.TestLint(' public:', '')
|
|
||||||
self.TestLint(' public:', '')
|
|
||||||
|
|
||||||
def testLabel(self):
|
def testSectionIndent(self):
|
||||||
self.TestLint('public:',
|
self.TestMultiLineLint(
|
||||||
'Labels should always be indented at least one space. '
|
"""
|
||||||
'If this is a member-initializer list in a constructor or '
|
class A {
|
||||||
'the base class list in a class definition, the colon should '
|
public: // no warning
|
||||||
'be on the following line. [whitespace/labels] [4]')
|
private: // warning here
|
||||||
self.TestLint(' public:', '')
|
};""",
|
||||||
self.TestLint(' public:', '')
|
'private: should be indented +1 space inside class A'
|
||||||
self.TestLint(' public:', '')
|
' [whitespace/indent] [3]')
|
||||||
self.TestLint(' public:', '')
|
self.TestMultiLineLint(
|
||||||
self.TestLint(' public:', '')
|
"""
|
||||||
|
class B {
|
||||||
def testNotALabel(self):
|
public: // no warning
|
||||||
self.TestLint('MyVeryLongNamespace::MyVeryLongClassName::', '')
|
template<> struct C {
|
||||||
|
public: // warning here
|
||||||
|
protected: // no warning
|
||||||
|
};
|
||||||
|
};""",
|
||||||
|
'public: should be indented +1 space inside struct C'
|
||||||
|
' [whitespace/indent] [3]')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
struct D {
|
||||||
|
};""",
|
||||||
|
'Closing brace should be aligned with beginning of struct D'
|
||||||
|
' [whitespace/indent] [3]')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
template<typename E> class F {
|
||||||
|
};""",
|
||||||
|
'Closing brace should be aligned with beginning of class F'
|
||||||
|
' [whitespace/indent] [3]')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
class G {
|
||||||
|
Q_OBJECT
|
||||||
|
public slots:
|
||||||
|
signals:
|
||||||
|
};""",
|
||||||
|
['public slots: should be indented +1 space inside class G'
|
||||||
|
' [whitespace/indent] [3]',
|
||||||
|
'signals: should be indented +1 space inside class G'
|
||||||
|
' [whitespace/indent] [3]'])
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
class H {
|
||||||
|
/* comments */ class I {
|
||||||
|
public: // no warning
|
||||||
|
private: // warning here
|
||||||
|
};
|
||||||
|
};""",
|
||||||
|
'private: should be indented +1 space inside class I'
|
||||||
|
' [whitespace/indent] [3]')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
class J
|
||||||
|
: public ::K {
|
||||||
|
public: // no warning
|
||||||
|
protected: // warning here
|
||||||
|
};""",
|
||||||
|
'protected: should be indented +1 space inside class J'
|
||||||
|
' [whitespace/indent] [3]')
|
||||||
|
self.TestMultiLineLint(
|
||||||
|
"""
|
||||||
|
class L
|
||||||
|
: public M,
|
||||||
|
public ::N {
|
||||||
|
};""",
|
||||||
|
'')
|
||||||
|
|
||||||
def testTab(self):
|
def testTab(self):
|
||||||
self.TestLint('\tint a;',
|
self.TestLint('\tint a;',
|
||||||
|
@ -2368,13 +2482,14 @@ class CpplintTest(CpplintTestBase):
|
||||||
};""",
|
};""",
|
||||||
'')
|
'')
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
"""class Foo
|
"""
|
||||||
|
class Foo
|
||||||
#ifdef DERIVE_FROM_GOO
|
#ifdef DERIVE_FROM_GOO
|
||||||
: public Goo {
|
: public Goo {
|
||||||
#else
|
#else
|
||||||
: public Hoo {
|
: public Hoo {
|
||||||
#endif
|
#endif
|
||||||
};""",
|
};""",
|
||||||
'')
|
'')
|
||||||
# Test incomplete class
|
# Test incomplete class
|
||||||
self.TestMultiLineLint(
|
self.TestMultiLineLint(
|
||||||
|
@ -2966,7 +3081,13 @@ class OrderOfIncludesTest(CpplintTestBase):
|
||||||
|
|
||||||
def testRegression(self):
|
def testRegression(self):
|
||||||
def Format(includes):
|
def Format(includes):
|
||||||
return ''.join(['#include %s\n' % include for include in includes])
|
include_list = []
|
||||||
|
for header_path in includes:
|
||||||
|
if header_path:
|
||||||
|
include_list.append('#include %s\n' % header_path)
|
||||||
|
else:
|
||||||
|
include_list.append('\n')
|
||||||
|
return ''.join(include_list)
|
||||||
|
|
||||||
# Test singleton cases first.
|
# Test singleton cases first.
|
||||||
self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo.h"']), '')
|
self.TestLanguageRulesCheck('foo/foo.cc', Format(['"foo/foo.h"']), '')
|
||||||
|
@ -2998,6 +3119,17 @@ class OrderOfIncludesTest(CpplintTestBase):
|
||||||
Format(['"foo/bar-inl.h"',
|
Format(['"foo/bar-inl.h"',
|
||||||
'"foo/foo-inl.h"']),
|
'"foo/foo-inl.h"']),
|
||||||
'')
|
'')
|
||||||
|
self.TestLanguageRulesCheck(
|
||||||
|
'foo/foo.cc',
|
||||||
|
Format(['"foo/e.h"',
|
||||||
|
'"foo/b.h"', # warning here (e>b)
|
||||||
|
'"foo/c.h"',
|
||||||
|
'"foo/d.h"',
|
||||||
|
'"foo/a.h"']), # warning here (d>a)
|
||||||
|
['Include "foo/b.h" not in alphabetical order'
|
||||||
|
' [build/include_alpha] [4]',
|
||||||
|
'Include "foo/a.h" not in alphabetical order'
|
||||||
|
' [build/include_alpha] [4]'])
|
||||||
# -inl.h headers are no longer special.
|
# -inl.h headers are no longer special.
|
||||||
self.TestLanguageRulesCheck('foo/foo.cc',
|
self.TestLanguageRulesCheck('foo/foo.cc',
|
||||||
Format(['"foo/foo-inl.h"', '<string>']),
|
Format(['"foo/foo-inl.h"', '<string>']),
|
||||||
|
@ -3030,6 +3162,21 @@ class OrderOfIncludesTest(CpplintTestBase):
|
||||||
'"base/google.h"',
|
'"base/google.h"',
|
||||||
'"base/google-inl.h"']),
|
'"base/google-inl.h"']),
|
||||||
'')
|
'')
|
||||||
|
# Allow project includes to be separated by blank lines
|
||||||
|
self.TestLanguageRulesCheck('a/a.cc',
|
||||||
|
Format(['"a/a.h"',
|
||||||
|
'<string>',
|
||||||
|
'"base/google.h"',
|
||||||
|
'',
|
||||||
|
'"a/b.h"']),
|
||||||
|
'')
|
||||||
|
self.TestLanguageRulesCheck('a/a.cc',
|
||||||
|
Format(['"a/a.h"',
|
||||||
|
'<string>',
|
||||||
|
'"base/google.h"',
|
||||||
|
'"a/b.h"']),
|
||||||
|
'Include "a/b.h" not in alphabetical '
|
||||||
|
'order [build/include_alpha] [4]')
|
||||||
|
|
||||||
|
|
||||||
class CheckForFunctionLengthsTest(CpplintTestBase):
|
class CheckForFunctionLengthsTest(CpplintTestBase):
|
||||||
|
@ -3386,6 +3533,7 @@ class NestnigStateTest(unittest.TestCase):
|
||||||
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
||||||
self.assertEquals(self.nesting_state.stack[0].name, 'A')
|
self.assertEquals(self.nesting_state.stack[0].name, 'A')
|
||||||
self.assertFalse(self.nesting_state.stack[0].is_derived)
|
self.assertFalse(self.nesting_state.stack[0].is_derived)
|
||||||
|
self.assertEquals(self.nesting_state.stack[0].class_indent, 0)
|
||||||
|
|
||||||
self.UpdateWithLines(['};',
|
self.UpdateWithLines(['};',
|
||||||
'struct B : public A {'])
|
'struct B : public A {'])
|
||||||
|
@ -3406,7 +3554,7 @@ class NestnigStateTest(unittest.TestCase):
|
||||||
'template<T>'])
|
'template<T>'])
|
||||||
self.assertEquals(len(self.nesting_state.stack), 0)
|
self.assertEquals(len(self.nesting_state.stack), 0)
|
||||||
|
|
||||||
self.UpdateWithLines(['class D {', 'class E {'])
|
self.UpdateWithLines(['class D {', ' class E {'])
|
||||||
self.assertEquals(len(self.nesting_state.stack), 2)
|
self.assertEquals(len(self.nesting_state.stack), 2)
|
||||||
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
||||||
self.assertEquals(self.nesting_state.stack[0].name, 'D')
|
self.assertEquals(self.nesting_state.stack[0].name, 'D')
|
||||||
|
@ -3414,6 +3562,7 @@ class NestnigStateTest(unittest.TestCase):
|
||||||
self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
|
self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
|
||||||
self.assertEquals(self.nesting_state.stack[1].name, 'E')
|
self.assertEquals(self.nesting_state.stack[1].name, 'E')
|
||||||
self.assertFalse(self.nesting_state.stack[1].is_derived)
|
self.assertFalse(self.nesting_state.stack[1].is_derived)
|
||||||
|
self.assertEquals(self.nesting_state.stack[1].class_indent, 2)
|
||||||
self.assertEquals(self.nesting_state.InnermostClass().name, 'E')
|
self.assertEquals(self.nesting_state.InnermostClass().name, 'E')
|
||||||
|
|
||||||
self.UpdateWithLines(['}', '}'])
|
self.UpdateWithLines(['}', '}'])
|
||||||
|
@ -3553,6 +3702,18 @@ class NestnigStateTest(unittest.TestCase):
|
||||||
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
||||||
self.assertEquals(self.nesting_state.stack[0].name, 'D')
|
self.assertEquals(self.nesting_state.stack[0].name, 'D')
|
||||||
|
|
||||||
|
def testTemplateInnerClass(self):
|
||||||
|
self.UpdateWithLines(['class A {',
|
||||||
|
' public:'])
|
||||||
|
self.assertEquals(len(self.nesting_state.stack), 1)
|
||||||
|
self.assertTrue(isinstance(self.nesting_state.stack[0], cpplint._ClassInfo))
|
||||||
|
|
||||||
|
self.UpdateWithLines([' template <class B>',
|
||||||
|
' class C<alloc<B> >',
|
||||||
|
' : public A {'])
|
||||||
|
self.assertEquals(len(self.nesting_state.stack), 2)
|
||||||
|
self.assertTrue(isinstance(self.nesting_state.stack[1], cpplint._ClassInfo))
|
||||||
|
|
||||||
def testArguments(self):
|
def testArguments(self):
|
||||||
self.UpdateWithLines(['class A {'])
|
self.UpdateWithLines(['class A {'])
|
||||||
self.assertEquals(len(self.nesting_state.stack), 1)
|
self.assertEquals(len(self.nesting_state.stack), 1)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user