Update cpplint.py to r456

456 - Tweak lint to sometimes allow { on line following array initialization.
455 - Recognize more types.
454 - Try a bit harder to detect templated types.
453 - Changed error message wording on build/storage_class to be less ambiguous.
452 - Recognize more types to silence false positives for brace warnings.
451 - <skipped>
450 - <skipped>
449 - Ignore whitespace/tab for Linux Kernel files.
448 - Remove some more false positive lint warnings for int64{n}.
447 - Just one warning message for line length is enough, don't need two.
446 - Allow braced conversions to int16, uint64, etc. per the style guide.
445 - Fixed handling of backslash escapes for checking whether a "//" is quoted.
444 - Reduced dependency on hardcoded .cc extension.
443 - Disable single-arg constructor checks by default, since ClangTidy has the
      same check. We could just delete the check entirely, but it's slightly
      useful in places that can't run ClangTidy.
442 - Fix matching of macro names in CheckTrailingSemicolon to include digits.
441 - Deleted checks:
      - All checks for RValue references.
      - Spacing check around boolean &&, because those look like RValue
        references.
      A huge amount of code and effort were dedicated to tell RValue
      references apart from boolean expressions, and to differentiate
      allowed versus banned RValue references. But we still get regular
      false positives from this one check. Rather than making the check
      more complex than what it already is, it seemed safer to just delete
      it altogether for now, and have a different process for catching
      RValue references.
440 - Add rule to cpplint to throw error on empty if statement bodies without
      else clauses. If statement bodies with comments are not considered empty.
439 - Allow spaces before closing brace of namespace block so that namespaces
      inside of macro definitions (where the entire macro definition is
      indented) are not treated as errors.
438 - cpplint: fix a false positive on `new const int(x)`.
437 - Only check for function length when current line is inside a function.
436 - cpplint: Catch static `std::string` instances as well as those written as
      `string`. Previously users would sometimes work around the lint warning by
      changing their code to even worse code by adding the "std::" prefix.
435 - cpplint: Be a little smarter about warning on indentation.
434 - cpplint: Remove false positives on some functions returning string const&.
433 - cpplint: improve diagnostics of global/static string objects.
432 - Allow non-const reference parameters for iostream based types.
431 - Better handling of raw strings inside comments.
430 - <noop>
429 - <skipped>
428 - <skipped>
427 - Add support to CHECK_NOTNULL when checking if a member variable is
      initialized with itself.
426 - Allow suppressing specific warnings in C headers.
425 - Allow spaces before parens for inline assembly.
424 - Remove lint checks for {EXPECT,ASSERT}_.*_M.
423 - Allow comment lines of more than 80 characters if they contain a single
      "word" (without any spaces).
422 - cpplint: Warn on inclusion of C++14 headers.
421 - cpplint: recognize <shared_mutex> as a standard library header.
420 - Add <scoped_allocator> to cpplint's list of C++ standard headers.
419 - Add cpplint check for tr1/ headers. We removed the nanny guards for these
418 - <skipped>
417 - Update the styleguide and cpplint to allow unnamed parameters
416 - Remove the rule explicitly banning non-default move operations.
415 - Remove the check for explicit multi arg constructors
414 - Include clarity of lambda default captures in "pros" section, mention
      of capturing `this` and lambdas which escape the current scope in "cons".
      Soften the ban on default captures to a preference, with admonition against
      using them for capturing `this` or when they will escape the current scope.
      This is a fairly straightforward change with a brief inclusion
      of 2 problematic cases for implicit capture. As this is the style
      guide, I'm not sure how much more detail is appropriate.
413 - Fixed a bug by making regex in CleanseRawStrings match multiple raw strings
      on a single line in left-to-right order.
412 - Fixed false positive for classes derived using decltype()
411 - <skipped>
410 - Recognize '1LL<<20' as numeric and don't flag it for spacing.
This commit is contained in:
Alex Vakulenko 2016-05-06 13:54:15 -07:00
parent 175866f6c4
commit 01e47236c8
2 changed files with 696 additions and 824 deletions

962
cpplint/cpplint.py vendored

File diff suppressed because it is too large Load Diff

View File

@ -290,6 +290,14 @@ class CpplintTest(CpplintTestBase):
results = self.GetNamespaceResults(lines) results = self.GetNamespaceResults(lines)
self.assertEquals(results, '') self.assertEquals(results, '')
def testWhitespaceBeforeNamespace(self):
lines = [' namespace Test {',
' void foo() { }',
' } // namespace Test']
results = self.GetNamespaceResults(lines)
self.assertEquals(results, '')
def testFalsePositivesNoError(self): def testFalsePositivesNoError(self):
lines = ['namespace Test {', lines = ['namespace Test {',
'struct OuterClass {', 'struct OuterClass {',
@ -362,13 +370,23 @@ class CpplintTest(CpplintTestBase):
'// Hello', '// Hello',
'') '')
self.TestLint( self.TestLint(
'// ' + 'x' * 80, '// x' + ' x' * 40,
'Lines should be <= 80 characters long' 'Lines should be <= 80 characters long'
' [whitespace/line_length] [2]') ' [whitespace/line_length] [2]')
self.TestLint( self.TestLint(
'// ' + 'x' * 100, '// x' + ' x' * 50,
'Lines should very rarely be longer than 100 characters' 'Lines should be <= 80 characters long'
' [whitespace/line_length] [4]') ' [whitespace/line_length] [2]')
self.TestLint(
'// //some/path/to/f' + ('i' * 100) + 'le',
'')
self.TestLint(
'// //some/path/to/f' + ('i' * 100) + 'le',
'')
self.TestLint(
'// //some/path/to/f' + ('i' * 50) + 'le and some comments',
'Lines should be <= 80 characters long'
' [whitespace/line_length] [2]')
self.TestLint( self.TestLint(
'// http://g' + ('o' * 100) + 'gle.com/', '// http://g' + ('o' * 100) + 'gle.com/',
'') '')
@ -445,6 +463,64 @@ class CpplintTest(CpplintTestBase):
''], ''],
error_collector) error_collector)
self.assertEquals('', error_collector.Results()) self.assertEquals('', error_collector.Results())
# LINT_C_FILE silences cast warnings for entire file.
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData('test.h', 'h',
['// Copyright 2014 Your Company.',
'// NOLINT(build/header_guard)',
'int64 a = (uint64) 65;',
'// LINT_C_FILE',
''],
error_collector)
self.assertEquals('', error_collector.Results())
# Vim modes silence cast warnings for entire file.
for modeline in ['vi:filetype=c',
'vi:sw=8 filetype=c',
'vi:sw=8 filetype=c ts=8',
'vi: filetype=c',
'vi: sw=8 filetype=c',
'vi: sw=8 filetype=c ts=8',
'vim:filetype=c',
'vim:sw=8 filetype=c',
'vim:sw=8 filetype=c ts=8',
'vim: filetype=c',
'vim: sw=8 filetype=c',
'vim: sw=8 filetype=c ts=8',
'vim: set filetype=c:',
'vim: set sw=8 filetype=c:',
'vim: set sw=8 filetype=c ts=8:',
'vim: set filetype=c :',
'vim: set sw=8 filetype=c :',
'vim: set sw=8 filetype=c ts=8 :',
'vim: se filetype=c:',
'vim: se sw=8 filetype=c:',
'vim: se sw=8 filetype=c ts=8:',
'vim: se filetype=c :',
'vim: se sw=8 filetype=c :',
'vim: se sw=8 filetype=c ts=8 :']:
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData('test.h', 'h',
['// Copyright 2014 Your Company.',
'// NOLINT(build/header_guard)',
'int64 a = (uint64) 65;',
'/* Prevent warnings about the modeline',
modeline,
'*/',
''],
error_collector)
self.assertEquals('', error_collector.Results())
# LINT_KERNEL_FILE silences whitespace/tab warnings for entire file.
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData('test.h', 'h',
['// Copyright 2014 Your Company.',
'// NOLINT(build/header_guard)',
'struct test {',
'\tint member;',
'};',
'// LINT_KERNEL_FILE',
''],
error_collector)
self.assertEquals('', error_collector.Results())
# Test Variable Declarations. # Test Variable Declarations.
def testVariableDeclarations(self): def testVariableDeclarations(self):
@ -509,14 +585,55 @@ class CpplintTest(CpplintTestBase):
self.TestLint('[](int/*unused*/) -> bool {', '') self.TestLint('[](int/*unused*/) -> bool {', '')
self.TestLint('[](int /*unused*/) -> bool {', '') self.TestLint('[](int /*unused*/) -> bool {', '')
self.TestLint('auto f = [](MyStruct* /*unused*/)->int {', '') self.TestLint('auto f = [](MyStruct* /*unused*/)->int {', '')
self.TestLint( self.TestLint('[](int) -> bool {', '')
'[](int) -> bool {', self.TestLint('auto f = [](MyStruct*)->int {', '')
'All parameters should be named in a function'
' [readability/function] [3]') # Cast with brace initializers
self.TestLint( self.TestLint('int64_t{4096} * 1000 * 1000', '')
'auto f = [](MyStruct*)->int {', self.TestLint('size_t{4096} * 1000 * 1000', '')
'All parameters should be named in a function' self.TestLint('uint_fast16_t{4096} * 1000 * 1000', '')
' [readability/function] [3]')
# Brace initializer with templated type
self.TestMultiLineLint(
"""
template <typename Type1,
typename Type2>
void Function(int arg1,
int arg2) {
variable &= ~Type1{0} - 1;
}""",
'')
self.TestMultiLineLint(
"""
template <typename Type>
class Class {
void Function() {
variable &= ~Type{0} - 1;
}
};""",
'')
self.TestMultiLineLint(
"""
template <typename Type>
class Class {
void Function() {
variable &= ~Type{0} - 1;
}
};""",
'')
self.TestMultiLineLint(
"""
namespace {
template <typename Type>
class Class {
void Function() {
if (block) {
variable &= ~Type{0} - 1;
}
}
};
}""",
'')
# Test taking address of casts (runtime/casting) # Test taking address of casts (runtime/casting)
def testRuntimeCasting(self): def testRuntimeCasting(self):
@ -559,6 +676,10 @@ class CpplintTest(CpplintTestBase):
'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }', 'Foo::Foo(Bar r, Bel l) : r_(r_), l_(l_) { }',
'You seem to be initializing a member variable with itself.' 'You seem to be initializing a member variable with itself.'
' [runtime/init] [4]') ' [runtime/init] [4]')
self.TestLint(
'Foo::Foo(Bar r, Bel l) : r_(CHECK_NOTNULL(r_)) { }',
'You seem to be initializing a member variable with itself.'
' [runtime/init] [4]')
self.TestLint( self.TestLint(
'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }', 'Foo::Foo(Bar r, Bel l) : r_(r), l_(l) { }',
'') '')
@ -568,14 +689,12 @@ class CpplintTest(CpplintTestBase):
# 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' self.TestLint('virtual void Func(int*) const;', '')
' [readability/function] [3]') self.TestLint('virtual void Func(int*);', '')
self.TestLint('virtual void Func(int*) const;', message) self.TestLint('void Method(char*) {', '')
self.TestLint('virtual void Func(int*);', message) self.TestLint('void Method(char*);', '')
self.TestLint('void Method(char*) {', message) self.TestLint('static void operator delete[](void*) throw();', '')
self.TestLint('void Method(char*);', message) self.TestLint('int Method(int);', '')
self.TestLint('static void operator delete[](void*) throw();', message)
self.TestLint('int Method(int);', message)
self.TestLint('virtual void Func(int* p);', '') self.TestLint('virtual void Func(int* p);', '')
self.TestLint('void operator delete(void* x) throw();', '') self.TestLint('void operator delete(void* x) throw();', '')
@ -627,6 +746,7 @@ class CpplintTest(CpplintTestBase):
self.TestLint('operator bool();', '') # Conversion operator self.TestLint('operator bool();', '') # Conversion operator
self.TestLint('new int64(123);', '') # "new" operator on basic type self.TestLint('new int64(123);', '') # "new" operator on basic type
self.TestLint('new int64(123);', '') # "new" operator on basic type self.TestLint('new int64(123);', '') # "new" operator on basic type
self.TestLint('new const int(42);', '') # "new" on const-qualified type
self.TestLint('using a = bool(int arg);', '') # C++11 alias-declaration self.TestLint('using a = bool(int arg);', '') # C++11 alias-declaration
self.TestLint('x = bit_cast<double(*)[3]>(y);', '') # array of array self.TestLint('x = bit_cast<double(*)[3]>(y);', '') # array of array
self.TestLint('void F(const char(&src)[N]);', '') # array of references self.TestLint('void F(const char(&src)[N]);', '') # array of references
@ -838,7 +958,7 @@ class CpplintTest(CpplintTestBase):
"""#include "base/foobar.h" """#include "base/foobar.h"
bool foobar = swap(0,1); bool foobar = swap(0,1);
""", """,
'Add #include <algorithm> for swap [build/include_what_you_use] [4]') 'Add #include <utility> for swap [build/include_what_you_use] [4]')
self.TestIncludeWhatYouUse( self.TestIncludeWhatYouUse(
"""#include "base/foobar.h" """#include "base/foobar.h"
bool foobar = transform(a.begin(), a.end(), b.start(), Foo); bool foobar = transform(a.begin(), a.end(), b.start(), Foo);
@ -1199,16 +1319,13 @@ class CpplintTest(CpplintTestBase):
};""", };""",
'Zero-parameter constructors should not be marked explicit.' 'Zero-parameter constructors should not be marked explicit.'
' [runtime/explicit] [5]') ' [runtime/explicit] [5]')
# Warn explicit multi-argument constructors at lowest severity # No warning for multi-parameter constructors
self.TestMultiLineLint( self.TestMultiLineLint(
""" """
class Foo { class Foo {
explicit Foo(int f, int g); explicit Foo(int f, int g);
};""", };""",
'Constructors that require multiple arguments ' '')
'should not be marked explicit. [runtime/explicit] [0]')
# but explicit multi-argument constructors with only one non-default
# argument are OK
self.TestMultiLineLint( self.TestMultiLineLint(
""" """
class Foo { class Foo {
@ -1863,18 +1980,6 @@ class CpplintTest(CpplintTestBase):
'EXPECT_TRUE(+42 >= x);', 'EXPECT_TRUE(+42 >= x);',
'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)' 'Consider using EXPECT_GE instead of EXPECT_TRUE(a >= b)'
' [readability/check] [2]') ' [readability/check] [2]')
self.TestLint(
'EXPECT_TRUE_M(-42 > x);',
'Consider using EXPECT_GT_M instead of EXPECT_TRUE_M(a > b)'
' [readability/check] [2]')
self.TestLint(
'EXPECT_TRUE_M(42U <= x);',
'Consider using EXPECT_LE_M instead of EXPECT_TRUE_M(a <= b)'
' [readability/check] [2]')
self.TestLint(
'EXPECT_TRUE_M(42L < x);',
'Consider using EXPECT_LT_M instead of EXPECT_TRUE_M(a < b)'
' [readability/check] [2]')
self.TestLint( self.TestLint(
'EXPECT_FALSE(x == 42);', 'EXPECT_FALSE(x == 42);',
@ -1896,10 +2001,6 @@ class CpplintTest(CpplintTestBase):
'ASSERT_FALSE(x <= 42);', 'ASSERT_FALSE(x <= 42);',
'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)' 'Consider using ASSERT_GT instead of ASSERT_FALSE(a <= b)'
' [readability/check] [2]') ' [readability/check] [2]')
self.TestLint(
'ASSERT_FALSE_M(x < 42);',
'Consider using ASSERT_GE_M instead of ASSERT_FALSE_M(a < b)'
' [readability/check] [2]')
self.TestLint('CHECK(x<42);', self.TestLint('CHECK(x<42);',
['Missing spaces around <' ['Missing spaces around <'
@ -2033,6 +2134,10 @@ class CpplintTest(CpplintTestBase):
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);', '')
self.TestLint('void swap(Bar& a, Bar& b);', '') self.TestLint('void swap(Bar& a, Bar& b);', '')
self.TestLint('ostream& LogFunc(ostream& s);', '')
self.TestLint('ostringstream& LogFunc(ostringstream& s);', '')
self.TestLint('istream& LogFunc(istream& s);', '')
self.TestLint('istringstream& LogFunc(istringstream& s);', '')
# Returning a non-const reference from a function is OK. # Returning a non-const reference from a function is OK.
self.TestLint('int& g();', '') self.TestLint('int& g();', '')
# Passing a const reference to a struct (using the struct keyword) is OK. # Passing a const reference to a struct (using the struct keyword) is OK.
@ -2282,6 +2387,9 @@ 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]')
# asm volatile () may have a space, as it isn't a function call.
self.TestLint('asm volatile ("")', '')
self.TestLint('__asm__ __volatile__ ("")', '')
self.TestLint('} catch (const Foo& ex) {', '') self.TestLint('} catch (const Foo& ex) {', '')
self.TestLint('case (42):', '') self.TestLint('case (42):', '')
self.TestLint('typedef foo (*foo)(foo)', '') self.TestLint('typedef foo (*foo)(foo)', '')
@ -2319,9 +2427,20 @@ class CpplintTest(CpplintTestBase):
self.TestLint('for {', '') self.TestLint('for {', '')
self.TestLint('EXPECT_DEBUG_DEATH({', '') self.TestLint('EXPECT_DEBUG_DEATH({', '')
self.TestLint('std::is_convertible<A, B>{}', '') self.TestLint('std::is_convertible<A, B>{}', '')
self.TestLint('blah{32}', 'Missing space before {'
' [whitespace/braces] [5]')
self.TestLint('int8_t{3}', '')
self.TestLint('int16_t{3}', '')
self.TestLint('int32_t{3}', '')
self.TestLint('uint64_t{12345}', '')
self.TestLint('constexpr int64_t kBatchGapMicros ='
' int64_t{7} * 24 * 3600 * 1000000; // 1 wk.', '')
self.TestLint('MoveOnly(int i1, int i2) : ip1{new int{i1}}, '
'ip2{new int{i2}} {}',
'')
def testSemiColonAfterBraces(self): def testSemiColonAfterBraces(self):
self.TestLint('if (cond) {};', self.TestLint('if (cond) { func(); };',
'You don\'t need a ; after a } [readability/braces] [4]') 'You don\'t need a ; after a } [readability/braces] [4]')
self.TestLint('void Func() {};', self.TestLint('void Func() {};',
'You don\'t need a ; after a } [readability/braces] [4]') 'You don\'t need a ; after a } [readability/braces] [4]')
@ -2337,8 +2456,11 @@ class CpplintTest(CpplintTestBase):
self.TestLint('class X : public Y {};', '') self.TestLint('class X : public Y {};', '')
self.TestLint('class X : public MACRO() {};', '') self.TestLint('class X : public MACRO() {};', '')
self.TestLint('class X : public decltype(expr) {};', '')
self.TestLint('DEFINE_FACADE(PCQueue::Watcher, PCQueue) {};', '') self.TestLint('DEFINE_FACADE(PCQueue::Watcher, PCQueue) {};', '')
self.TestLint('VCLASS(XfaTest, XfaContextTest) {};', '') self.TestLint('VCLASS(XfaTest, XfaContextTest) {};', '')
self.TestLint('class STUBBY_CLASS(H, E) {};', '')
self.TestLint('class STUBBY2_CLASS(H, E) {};', '')
self.TestLint('TEST(TestCase, TestName) {};', self.TestLint('TEST(TestCase, TestName) {};',
'You don\'t need a ; after a } [readability/braces] [4]') 'You don\'t need a ; after a } [readability/braces] [4]')
self.TestLint('TEST_F(TestCase, TestName) {};', self.TestLint('TEST_F(TestCase, TestName) {};',
@ -2365,19 +2487,6 @@ class CpplintTest(CpplintTestBase):
'};\n', '};\n',
'') '')
for lambda_with_default_capture in ('void f() { [=]{}; }',
'void f() { [=](int i) {}; }',
'void f() { [=, &x]{}; }',
'void f() { [&]{}; }',
'void f() { [ & ]{}; }',
'void f() { [&, y]{}; }'):
self.TestLint(lambda_with_default_capture,
'Default lambda captures are an unapproved C++ feature. '
'[build/c++11] [4]')
# "[&...]" isn't necessarily a default capture, though "[=...]" always is.
self.TestLint('void f() { [&variable]{}; }', '')
# Avoid false positives with operator[] # Avoid false positives with operator[]
self.TestLint('table_to_children[&*table].push_back(dependent);', '') self.TestLint('table_to_children[&*table].push_back(dependent);', '')
@ -2412,13 +2521,28 @@ class CpplintTest(CpplintTestBase):
' }\n' ' }\n'
'};\n', '') '};\n', '')
self.TestMultiLineLint('if (true) {\n' self.TestMultiLineLint('if (true) {\n'
' if (false){}\n' ' if (false){ func(); }\n'
'}\n', '}\n',
'Missing space before { [whitespace/braces] [5]') 'Missing space before { [whitespace/braces] [5]')
self.TestMultiLineLint('MyClass::MyClass()\n' self.TestMultiLineLint('MyClass::MyClass()\n'
' : initializer_{\n' ' : initializer_{\n'
' Func()} {\n' ' Func()} {\n'
'}\n', '') '}\n', '')
self.TestLint('const pair<string, string> kCL' +
('o' * 41) + 'gStr[] = {\n',
'Lines should be <= 80 characters long'
' [whitespace/line_length] [2]')
self.TestMultiLineLint('const pair<string, string> kCL' +
('o' * 40) + 'ngStr[] =\n'
' {\n'
' {"gooooo", "oooogle"},\n'
'};\n', '')
self.TestMultiLineLint('const pair<string, string> kCL' +
('o' * 39) + 'ngStr[] =\n'
' {\n'
' {"gooooo", "oooogle"},\n'
'};\n', '{ should almost always be at the end of '
'the previous line [whitespace/braces] [4]')
def testSpacingAroundElse(self): def testSpacingAroundElse(self):
self.TestLint('}else {', 'Missing space before else' self.TestLint('}else {', 'Missing space before else'
@ -2455,6 +2579,7 @@ class CpplintTest(CpplintTestBase):
'Missing spaces around << [whitespace/operators] [3]') 'Missing spaces around << [whitespace/operators] [3]')
self.TestLint('a<<b', self.TestLint('a<<b',
'Missing spaces around << [whitespace/operators] [3]') 'Missing spaces around << [whitespace/operators] [3]')
self.TestLint('10LL<<20', '')
self.TestLint('10ULL<<20', '') self.TestLint('10ULL<<20', '')
self.TestLint('a>>b', self.TestLint('a>>b',
'Missing spaces around >> [whitespace/operators] [3]') 'Missing spaces around >> [whitespace/operators] [3]')
@ -2481,141 +2606,6 @@ class CpplintTest(CpplintTestBase):
self.TestLint('using Vector3<T>::operator==;', '') self.TestLint('using Vector3<T>::operator==;', '')
self.TestLint('using Vector3<T>::operator!=;', '') self.TestLint('using Vector3<T>::operator!=;', '')
def testRvalueReference(self):
space_error = 'Missing spaces around && [whitespace/operators] [3]'
rvalue_error = ('RValue references are an unapproved C++ feature.'
' [build/c++11] [3]')
# Places where lack of space are allowed
self.TestLint('DEFINE_BINARY_OPERATOR(&&)', '')
self.TestLint('bool operator&&(A b) {}', '')
self.TestLint('bool operator&&(A b) {', '')
self.TestLint('bool operator&&(A b);', '')
# Assignment expressions
self.TestLint('a = b && c;', '')
self.TestLint('a = b&& c;', space_error)
self.TestLint('a = b &&c;', space_error)
self.TestLint('a = (b&& c);', space_error)
self.TestLint('a = (b &&c);', space_error)
self.TestLint('a&& b = c;', rvalue_error)
self.TestLint('a<b>&& c = d;', rvalue_error)
self.TestLint('auto&& a = b;', rvalue_error)
self.TestLint('const a&& b = c;', rvalue_error)
self.TestLint('struct a&& b = c;', rvalue_error)
self.TestLint('decltype(a)&& b = c;', rvalue_error)
# Cast expressions
self.TestLint('a = const_cast<b&&>(c);', rvalue_error)
self.TestLint('a = const_cast<const b&&>(c);', rvalue_error)
self.TestLint('a = static_cast<b&&>(c);', rvalue_error)
self.TestLint('a = static_cast<const b&&>(c);', rvalue_error)
self.TestLint('a = dynamic_cast<b&&>(c);', rvalue_error)
self.TestLint('a = dynamic_cast<const b&&>(c);', rvalue_error)
self.TestLint('a = reinterpret_cast<b&&>(c);', rvalue_error)
self.TestLint('a = reinterpret_cast<const b&&>(c);', rvalue_error)
self.TestLint('a = cast < b&& c;', space_error)
# Function parameters
for indent in ['', ' ']:
for head in ['void Func', 'vector<int> Func', 'vector<int>\nFunc',
'inline void Func',
'Constructor', 'Constructor::Constructor',
'operator=', 'operator =', 'operator = ']:
for body in [' {}', ' {', ';']:
self.TestMultiLineLint(indent + head + '(A&& b)' + body, rvalue_error)
self.TestMultiLineLint(indent + head + '(A &&b)' + body, rvalue_error)
self.TestMultiLineLint(indent + head + '(A&&... b)' + body,
rvalue_error)
self.TestMultiLineLint(indent + head + '(A<B>&& c)' + body,
rvalue_error)
self.TestMultiLineLint(indent + head + '(A<B> &&c)' + body,
rvalue_error)
# Function templates
self.TestLint('std::conditional<A, B&, C&&>::type', rvalue_error)
self.TestLint('std::conditional<A, B&&, C&>::type', rvalue_error)
# Template functions
self.TestLint('template <typename T> R&& F()', rvalue_error)
self.TestLint('template <typename T> R&& F() {', rvalue_error)
self.TestMultiLineLint('template <typename T>\nR&& F()', rvalue_error)
self.TestMultiLineLint('template <typename T>\nR&& F() {', rvalue_error)
self.TestLint('template <typename T> void F(T a, R&& b)', rvalue_error)
self.TestLint('template <typename T> void F(T a, R &&b)', rvalue_error)
self.TestLint('template <typename T> void F(T a, R&& b) {', rvalue_error)
# For loops
self.TestLint('for (a&& b;;)', rvalue_error)
self.TestLint('for (a&& b;;) {', rvalue_error)
self.TestLint('for (; a&& b;)', space_error)
self.TestLint('for (; a&& b;) {', space_error)
# Constructors
self.TestLint('A(a&& b)', rvalue_error)
self.TestLint('explicit A(a&& b)', rvalue_error)
self.TestLint('A(a b) : c(d&& e)', space_error)
self.TestLint('A(a b) : c(), d(e&& f)', space_error)
def testAllowedRvalueReference(self):
# Verify that RValue reference warnings for a line range can be silenced
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData('foo.cc', 'cc',
['// Copyright 2014 Your Company.',
'GOOGLE_ALLOW_RVALUE_REFERENCES_PUSH',
'void F(A&& b);',
'GOOGLE_ALLOW_RVALUE_REFERENCES_POP',
''],
error_collector)
self.assertEquals(error_collector.Results(), '')
# RValue references for constructors and operator=
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData(
'foo.cc', 'cc',
['// Copyright 2014 Your Company.',
'class X {',
' X(X&& param) = delete; // NOLINT(runtime/explicit)',
' X(X &&param) = default; // NOLINT(runtime/explicit)',
' inline X(X&& param) = default; // NOLINT(runtime/explicit)',
'',
' X& operator=(X&& param) = delete;',
' X& operator=(X&& param) = default;',
'};',
'A::A(A&&) = default;',
'Outer::Inner::Inner(Inner&&) = default;',
''],
error_collector)
self.assertEquals(error_collector.Results(), '')
# Assume templated function parameters are forwarded, and are allowed
error_collector = ErrorCollector(self.assert_)
cpplint.ProcessFileData(
'foo.cc', 'cc',
['// Copyright 2014 Your Company.',
'template <typename Allowed1>',
'void Function1(Allowed1&& a);',
'',
'template <typename Allowed2, typename Allowed3>',
'void Function2(Allowed2&& a, Allowed3 &&b) {',
'}',
'',
'template <class Allowed4>',
'void Function3(Ignored1 *a, Allowed4&& b) {',
'}',
'',
'template <typename... Allowed5>',
'void Function4(Allowed5&&... a) {',
'}',
'',
'template <class... Allowed6>',
'void Function5(',
' Allowed6 &&...a) {',
'}',
''],
error_collector)
self.assertEquals(error_collector.Results(), '')
def testSpacingBeforeLastSemicolon(self): def testSpacingBeforeLastSemicolon(self):
self.TestLint('call_function() ;', self.TestLint('call_function() ;',
'Extra space before last semicolon. If this should be an ' 'Extra space before last semicolon. If this should be an '
@ -2649,6 +2639,11 @@ class CpplintTest(CpplintTestBase):
self.TestLint('for (;;)', '') self.TestLint('for (;;)', '')
self.TestLint('for (;;) continue;', '') self.TestLint('for (;;) continue;', '')
self.TestLint('for (;;) func();', '') self.TestLint('for (;;) func();', '')
self.TestLint('if (test) {}',
'If statement had no body and no else clause'
' [whitespace/empty_if_body] [4]')
self.TestLint('if (test) func();', '')
self.TestLint('if (test) {} else {}', '')
self.TestMultiLineLint("""while (true && self.TestMultiLineLint("""while (true &&
false);""", false);""",
'Empty loop bodies should use {} or continue' 'Empty loop bodies should use {} or continue'
@ -2665,6 +2660,39 @@ class CpplintTest(CpplintTestBase):
while (false);""", while (false);""",
'Empty loop bodies should use {} or continue' 'Empty loop bodies should use {} or continue'
' [whitespace/empty_loop_body] [5]') ' [whitespace/empty_loop_body] [5]')
self.TestMultiLineLint("""if (test) {
}""",
'If statement had no body and no else clause'
' [whitespace/empty_if_body] [4]')
self.TestMultiLineLint("""if (test,
func({})) {
}""",
'If statement had no body and no else clause'
' [whitespace/empty_if_body] [4]')
self.TestMultiLineLint("""if (test)
func();""", '')
self.TestLint('if (test) { hello; }', '')
self.TestLint('if (test({})) { hello; }', '')
self.TestMultiLineLint("""if (test) {
func();
}""", '')
self.TestMultiLineLint("""if (test) {
// multiline
// comment
}""", '')
self.TestMultiLineLint("""if (test) { // comment
}""", '')
self.TestMultiLineLint("""if (test) {
} else {
}""", '')
self.TestMultiLineLint("""if (func(p1,
p2,
p3)) {
func();
}""", '')
self.TestMultiLineLint("""if (func({}, p1)) {
func();
}""", '')
def testSpacingForRangeBasedFor(self): def testSpacingForRangeBasedFor(self):
# Basic correctly formatted case: # Basic correctly formatted case:
@ -2693,19 +2721,49 @@ class CpplintTest(CpplintTestBase):
# Static or global STL strings. # Static or global STL strings.
def testStaticOrGlobalSTLStrings(self): def testStaticOrGlobalSTLStrings(self):
# A template for the error message for a const global/static string.
error_msg = ('For a static/global string constant, use a C style ' error_msg = ('For a static/global string constant, use a C style '
'string instead: "%s[]". [runtime/string] [4]') 'string instead: "%s[]". [runtime/string] [4]')
# The error message for a non-const global/static string variable.
nonconst_error_msg = ('Static/global string variables are not permitted.'
' [runtime/string] [4]')
self.TestLint('string foo;', self.TestLint('string foo;',
error_msg % 'char foo') nonconst_error_msg)
self.TestLint('string kFoo = "hello"; // English', self.TestLint('string kFoo = "hello"; // English',
error_msg % 'char kFoo') nonconst_error_msg)
self.TestLint('static string foo;', self.TestLint('static string foo;',
error_msg % 'static char foo') nonconst_error_msg)
self.TestLint('static const string foo;', self.TestLint('static const string foo;',
error_msg % 'static const char foo') error_msg % 'static const char foo')
self.TestLint('static const std::string foo;',
error_msg % 'static const char foo')
self.TestLint('string Foo::bar;', self.TestLint('string Foo::bar;',
error_msg % 'char Foo::bar') nonconst_error_msg)
self.TestLint('std::string foo;',
nonconst_error_msg)
self.TestLint('std::string kFoo = "hello"; // English',
nonconst_error_msg)
self.TestLint('static std::string foo;',
nonconst_error_msg)
self.TestLint('static const std::string foo;',
error_msg % 'static const char foo')
self.TestLint('std::string Foo::bar;',
nonconst_error_msg)
self.TestLint('::std::string foo;',
nonconst_error_msg)
self.TestLint('::std::string kFoo = "hello"; // English',
nonconst_error_msg)
self.TestLint('static ::std::string foo;',
nonconst_error_msg)
self.TestLint('static const ::std::string foo;',
error_msg % 'static const char foo')
self.TestLint('::std::string Foo::bar;',
nonconst_error_msg)
self.TestLint('string* pointer', '') self.TestLint('string* pointer', '')
self.TestLint('string *pointer', '') self.TestLint('string *pointer', '')
self.TestLint('string* pointer = Func();', '') self.TestLint('string* pointer = Func();', '')
@ -2725,12 +2783,14 @@ class CpplintTest(CpplintTestBase):
self.TestLint('string Foo::bar() {}', '') self.TestLint('string Foo::bar() {}', '')
self.TestLint('string Foo::operator*() {}', '') self.TestLint('string Foo::operator*() {}', '')
# Rare case. # Rare case.
self.TestLint('string foo("foobar");', error_msg % 'char foo') self.TestLint('string foo("foobar");', nonconst_error_msg)
# Should not catch local or member variables. # Should not catch local or member variables.
self.TestLint(' string foo', '') self.TestLint(' string foo', '')
# Should not catch functions. # Should not catch functions.
self.TestLint('string EmptyString() { return ""; }', '') self.TestLint('string EmptyString() { return ""; }', '')
self.TestLint('string EmptyString () { return ""; }', '') self.TestLint('string EmptyString () { return ""; }', '')
self.TestLint('string const& FileInfo::Pathname() const;', '')
self.TestLint('string const &FileInfo::Pathname() const;', '')
self.TestLint('string VeryLongNameFunctionSometimesEndsWith(\n' self.TestLint('string VeryLongNameFunctionSometimesEndsWith(\n'
' VeryLongNameType very_long_name_variable) {}', '') ' VeryLongNameType very_long_name_variable) {}', '')
self.TestLint('template<>\n' self.TestLint('template<>\n'
@ -2761,21 +2821,24 @@ class CpplintTest(CpplintTestBase):
'NestedClass::MemberFunction3();', 'NestedClass::MemberFunction3();',
'string TemplateClass<T>::', 'string TemplateClass<T>::',
'NestedClass::MemberFunction4();', 'NestedClass::MemberFunction4();',
'string Class', 'const string Class',
'::static_member_variable1;', '::static_member_variable1;',
'string Class::', 'const string Class::',
'static_member_variable2;', 'static_member_variable2;',
'string Class', 'const string Class',
'::static_member_variable3 = "initial value";', '::static_member_variable3 = "initial value";',
'string Class::', 'const string Class::',
'static_member_variable4 = "initial value";', 'static_member_variable4 = "initial value";',
'string Class::',
'static_member_variable5;',
''], ''],
error_collector) error_collector)
self.assertEquals(error_collector.Results(), self.assertEquals(error_collector.Results(),
[error_msg % 'char Class::static_member_variable1', [error_msg % 'const char Class::static_member_variable1',
error_msg % 'char Class::static_member_variable2', error_msg % 'const char Class::static_member_variable2',
error_msg % 'char Class::static_member_variable3', error_msg % 'const char Class::static_member_variable3',
error_msg % 'char Class::static_member_variable4']) error_msg % 'const char Class::static_member_variable4',
nonconst_error_msg])
def testNoSpacesInFunctionCalls(self): def testNoSpacesInFunctionCalls(self):
self.TestLint('TellStory(1, 3);', self.TestLint('TellStory(1, 3);',
@ -2825,6 +2888,9 @@ class CpplintTest(CpplintTestBase):
self.TestLint('// TODO(ljenkins): Fix this', '') self.TestLint('// TODO(ljenkins): Fix this', '')
self.TestLint('#if 1 // TEST_URLTODOCID_WHICH_HAS_THAT_WORD_IN_IT_H_', '') self.TestLint('#if 1 // TEST_URLTODOCID_WHICH_HAS_THAT_WORD_IN_IT_H_', '')
self.TestLint('// See also similar TODO above', '') self.TestLint('// See also similar TODO above', '')
self.TestLint(r'EXPECT_EQ("\\", '
r'NormalizePath("/./../foo///bar/..//x/../..", ""));',
'')
def testTwoSpacesBetweenCodeAndComments(self): def testTwoSpacesBetweenCodeAndComments(self):
self.TestLint('} // namespace foo', self.TestLint('} // namespace foo',
@ -3360,10 +3426,9 @@ class CpplintTest(CpplintTestBase):
'') '')
self.TestMultiLineLint( self.TestMultiLineLint(
TrimExtraIndent(''' TrimExtraIndent('''
static const char kNotRawString[] = "(" KV<Query,
")";'''), Tuple<TaxonomyId, PetacatCategoryId, double>>'''),
'Weird number of spaces at line-start. ' '')
'Are you using a 2-space indent? [whitespace/indent] [3]')
self.TestMultiLineLint( self.TestMultiLineLint(
' static const char kSingleLineRawString[] = R"(...)";', ' static const char kSingleLineRawString[] = R"(...)";',
'Weird number of spaces at line-start. ' 'Weird number of spaces at line-start. '
@ -3723,18 +3788,18 @@ class CpplintTest(CpplintTestBase):
try: try:
cpplint._line_length = 80 cpplint._line_length = 80
self.TestLint( self.TestLint(
'// %s' % ('H' * 77), '// H %s' % ('H' * 75),
'') '')
self.TestLint( self.TestLint(
'// %s' % ('H' * 78), '// H %s' % ('H' * 76),
'Lines should be <= 80 characters long' 'Lines should be <= 80 characters long'
' [whitespace/line_length] [2]') ' [whitespace/line_length] [2]')
cpplint._line_length = 120 cpplint._line_length = 120
self.TestLint( self.TestLint(
'// %s' % ('H' * 117), '// H %s' % ('H' * 115),
'') '')
self.TestLint( self.TestLint(
'// %s' % ('H' * 118), '// H %s' % ('H' * 116),
'Lines should be <= 120 characters long' 'Lines should be <= 120 characters long'
' [whitespace/line_length] [2]') ' [whitespace/line_length] [2]')
finally: finally:
@ -3873,7 +3938,8 @@ class CpplintTest(CpplintTestBase):
cpplint.ProcessFileData(file_path, 'h', [], error_collector) cpplint.ProcessFileData(file_path, 'h', [], error_collector)
for error in error_collector.ResultList(): for error in error_collector.ResultList():
matched = re.search( matched = re.search(
'No #ifndef header guard found, suggested CPP variable is: ([A-Z_]+)', 'No #ifndef header guard found, suggested CPP variable is: '
'([A-Z0-9_]+)',
error) error)
if matched is not None: if matched is not None:
return matched.group(1) return matched.group(1)
@ -4176,8 +4242,8 @@ class CpplintTest(CpplintTestBase):
storage_classes = ['extern', 'register', 'static', 'typedef'] storage_classes = ['extern', 'register', 'static', 'typedef']
build_storage_class_error_message = ( build_storage_class_error_message = (
'Storage class (static, extern, typedef, etc) should be first.' 'Storage-class specifier (static, extern, typedef, etc) should be '
' [build/storage_class] [5]') 'at the beginning of the declaration. [build/storage_class] [5]')
# Some explicit cases. Legal in C++, deprecated in C99. # Some explicit cases. Legal in C++, deprecated in C99.
self.TestLint('const int static foo = 5;', self.TestLint('const int static foo = 5;',
@ -4309,6 +4375,9 @@ class Cxx11Test(CpplintTestBase):
self.assertEquals(expected_error, collector.Results()) self.assertEquals(expected_error, collector.Results())
def testBlockedHeaders(self): def testBlockedHeaders(self):
self.TestCxx11Feature('#include <tr1/regex>',
'C++ TR1 headers such as <tr1/regex> are '
'unapproved. [build/c++tr1] [5]')
self.TestCxx11Feature('#include <mutex>', self.TestCxx11Feature('#include <mutex>',
'<mutex> is an unapproved C++11 header.' '<mutex> is an unapproved C++11 header.'
' [build/c++11] [5]') ' [build/c++11] [5]')
@ -4353,6 +4422,25 @@ class Cxx11Test(CpplintTestBase):
' [build/explicit_make_pair] [4]') ' [build/explicit_make_pair] [4]')
self.TestLint('my_make_pair<int, int>', '') self.TestLint('my_make_pair<int, int>', '')
class Cxx14Test(CpplintTestBase):
def TestCxx14Feature(self, code, expected_error):
lines = code.split('\n')
collector = ErrorCollector(self.assert_)
cpplint.RemoveMultiLineComments('foo.h', lines, collector)
clean_lines = cpplint.CleansedLines(lines)
cpplint.FlagCxx14Features('foo.cc', clean_lines, 0, collector)
self.assertEquals(expected_error, collector.Results())
def testBlockedHeaders(self):
self.TestCxx14Feature('#include <scoped_allocator>',
'<scoped_allocator> is an unapproved C++14 header.'
' [build/c++14] [5]')
self.TestCxx14Feature('#include <shared_mutex>',
'<shared_mutex> is an unapproved C++14 header.'
' [build/c++14] [5]')
class CleansedLinesTest(unittest.TestCase): class CleansedLinesTest(unittest.TestCase):
def testInit(self): def testInit(self):
@ -4970,6 +5058,20 @@ class CheckForFunctionLengthsTest(CpplintTestBase):
'Lint failed to find start of function body.' 'Lint failed to find start of function body.'
' [readability/fn_size] [5]') ' [readability/fn_size] [5]')
def testFunctionLengthCheckWithNamespace(self):
old_verbosity = cpplint._SetVerboseLevel(1)
self.TestFunctionLengthsCheck(
('namespace {\n'
'void CodeCoverageCL35256059() {\n' +
(' X++;\n' * 3000) +
'}\n'
'} // namespace\n'),
('Small and focused functions are preferred: '
'CodeCoverageCL35256059() has 3000 non-comment lines '
'(error triggered by exceeding 20 lines).'
' [readability/fn_size] [5]'))
cpplint._SetVerboseLevel(old_verbosity)
def TrimExtraIndent(text_block): def TrimExtraIndent(text_block):
"""Trim a uniform amount of whitespace off of each line in a string. """Trim a uniform amount of whitespace off of each line in a string.