|
43 | 43 | import sys |
44 | 44 | import tempfile |
45 | 45 | import unittest |
46 | | - |
| 46 | +from parameterized import parameterized |
47 | 47 | import pytest |
48 | 48 |
|
49 | 49 | import cpplint |
@@ -229,6 +229,12 @@ def PerformIncludeWhatYouUse(self, code, filename='foo.h', io=codecs): |
229 | 229 | error_collector, io) |
230 | 230 | return error_collector.Results() |
231 | 231 |
|
| 232 | + # Perform lint and make sure one of the errors is what we want |
| 233 | + def TestLintContains(self, code, expected_message): |
| 234 | + self.assertTrue(expected_message in self.PerformSingleLineLint(code)) |
| 235 | + def TestLintNotContains(self, code, expected_message): |
| 236 | + self.assertFalse(expected_message in self.PerformSingleLineLint(code)) |
| 237 | + |
232 | 238 | # Perform lint and compare the error message with "expected_message". |
233 | 239 | def TestLint(self, code, expected_message): |
234 | 240 | self.assertEqual(expected_message, self.PerformSingleLineLint(code)) |
@@ -268,7 +274,6 @@ def doTestBlankLinesCheck(self, lines, start_errors, end_errors, extension): |
268 | 274 | 'Redundant blank line at the end of a code block ' |
269 | 275 | 'should be deleted. [whitespace/blank_line] [3]')) |
270 | 276 |
|
271 | | - |
272 | 277 | class CpplintTest(CpplintTestBase): |
273 | 278 |
|
274 | 279 | def GetNamespaceResults(self, lines): |
@@ -2217,6 +2222,14 @@ def testBraces(self): |
2217 | 2222 | { { 1, 2 }, |
2218 | 2223 | { 3, 4 } };""", |
2219 | 2224 | '') |
| 2225 | + self.TestMultiLineLint( # should not claim else should have braces on both sides |
| 2226 | + """if (foo) { |
| 2227 | + bar; |
| 2228 | + } |
| 2229 | + else { |
| 2230 | + baz; |
| 2231 | + }""", |
| 2232 | + 'An else should appear on the same line as the preceding } [whitespace/newline] [4]') |
2220 | 2233 |
|
2221 | 2234 | # CHECK/EXPECT_TRUE/EXPECT_FALSE replacements |
2222 | 2235 | def testCheckCheck(self): |
@@ -2458,7 +2471,9 @@ def testNonConstReference(self): |
2458 | 2471 | operand_error_message % 'std::vector<int>& p') |
2459 | 2472 | # Returning an address of something is not prohibited. |
2460 | 2473 | self.TestLint('return &something;', '') |
2461 | | - self.TestLint('if (condition) {return &something; }', '') |
| 2474 | + self.TestLint('if (condition) {return &something; }', |
| 2475 | + 'Controlled statements inside brackets of if clause should be on a separate line' |
| 2476 | + ' [whitespace/newline] [5]') |
2462 | 2477 | self.TestLint('if (condition) return &something;', '') |
2463 | 2478 | self.TestLint('if (condition) address = &something;', '') |
2464 | 2479 | self.TestLint('if (condition) result = lhs&rhs;', '') |
@@ -2656,8 +2671,8 @@ def testSpacingForFncall(self): |
2656 | 2671 | self.TestLint('for (foo;bar;baz) {', 'Missing space after ;' |
2657 | 2672 | ' [whitespace/semicolon] [3]') |
2658 | 2673 | # we don't warn about this semicolon, at least for now |
2659 | | - self.TestLint('if (condition) {return &something; }', |
2660 | | - '') |
| 2674 | + self.TestLintNotContains('if (condition) { return &something; }', |
| 2675 | + 'Missing space after ; [whitespace/semicolon] [3]') |
2661 | 2676 | # seen in some macros |
2662 | 2677 | self.TestLint('DoSth();\\', '') |
2663 | 2678 | # Test that there is no warning about semicolon here. |
@@ -2765,7 +2780,7 @@ def testSpacingBeforeBraces(self): |
2765 | 2780 | '') |
2766 | 2781 |
|
2767 | 2782 | def testSemiColonAfterBraces(self): |
2768 | | - self.TestLint('if (cond) { func(); };', |
| 2783 | + self.TestLintContains('if (cond) { func(); };', |
2769 | 2784 | 'You don\'t need a ; after a } [readability/braces] [4]') |
2770 | 2785 | self.TestLint('void Func() {};', |
2771 | 2786 | 'You don\'t need a ; after a } [readability/braces] [4]') |
@@ -2854,7 +2869,9 @@ def testBraceInitializerList(self): |
2854 | 2869 | ' }\n' |
2855 | 2870 | '};\n', '') |
2856 | 2871 | self.TestMultiLineLint('if (true) {\n' |
2857 | | - ' if (false){ func(); }\n' |
| 2872 | + ' if (false){\n' |
| 2873 | + ' func();\n' |
| 2874 | + ' }' |
2858 | 2875 | '}\n', |
2859 | 2876 | 'Missing space before { [whitespace/braces] [5]') |
2860 | 2877 | self.TestMultiLineLint('MyClass::MyClass()\n' |
@@ -3004,8 +3021,12 @@ def testEmptyBlockBody(self): |
3004 | 3021 | ' [whitespace/empty_if_body] [4]') |
3005 | 3022 | self.TestMultiLineLint("""if (test) |
3006 | 3023 | func();""", '') |
3007 | | - self.TestLint('if (test) { hello; }', '') |
3008 | | - self.TestLint('if (test({})) { hello; }', '') |
| 3024 | + self.TestLint('if (test) { hello; }', |
| 3025 | + 'Controlled statements inside brackets of if clause should be on a separate line' |
| 3026 | + ' [whitespace/newline] [5]') |
| 3027 | + self.TestLint('if (test({})) { hello; }', |
| 3028 | + 'Controlled statements inside brackets of if clause should be on a separate line' |
| 3029 | + ' [whitespace/newline] [5]') |
3009 | 3030 | self.TestMultiLineLint("""if (test) { |
3010 | 3031 | func(); |
3011 | 3032 | }""", '') |
@@ -3707,16 +3728,6 @@ def testEndOfNamespaceComments(self): |
3707 | 3728 | 'Namespace should be terminated with "// namespace no_warning"' |
3708 | 3729 | ' [readability/namespace] [5]')) |
3709 | 3730 |
|
3710 | | - def testElseClauseNotOnSameLineAsElse(self): |
3711 | | - self.TestLint(' else DoSomethingElse();', |
3712 | | - 'Else clause should never be on same line as else ' |
3713 | | - '(use 2 lines) [whitespace/newline] [4]') |
3714 | | - self.TestLint(' else ifDoSomethingElse();', |
3715 | | - 'Else clause should never be on same line as else ' |
3716 | | - '(use 2 lines) [whitespace/newline] [4]') |
3717 | | - self.TestLint(' } else if (blah) {', '') |
3718 | | - self.TestLint(' variable_ends_in_else = true;', '') |
3719 | | - |
3720 | 3731 | def testComma(self): |
3721 | 3732 | self.TestLint('a = f(1,2);', |
3722 | 3733 | 'Missing space after , [whitespace/comma] [3]') |
@@ -4094,13 +4105,6 @@ def testConditionals(self): |
4094 | 4105 | }""", |
4095 | 4106 | '{ should almost always be at the end of the previous line' |
4096 | 4107 | ' [whitespace/braces] [4]') |
4097 | | - self.TestMultiLineLint( |
4098 | | - """ |
4099 | | - if (foo) { \\ |
4100 | | - bar; \\ |
4101 | | - baz; \\ |
4102 | | - }""", |
4103 | | - '') |
4104 | 4108 | self.TestMultiLineLint( |
4105 | 4109 | """ |
4106 | 4110 | void foo() { if (bar) baz; }""", |
@@ -4141,6 +4145,33 @@ def testConditionals(self): |
4141 | 4145 | #endif""", |
4142 | 4146 | '') |
4143 | 4147 |
|
| 4148 | + @parameterized.expand(['else if', 'if', 'while', 'for', 'switch']) |
| 4149 | + def testControlClauseWithParensNewline(self, keyword): |
| 4150 | + # The % 2 part is pseudorandom whitespace-support testing |
| 4151 | + self.TestLintContains( |
| 4152 | + f'{keyword}{["", " "][len(keyword) % 2]}(condition)' |
| 4153 | + f'{[" ", ""][len(keyword) % 2]}[[unlikely]]' |
| 4154 | + f'{[" ", ""][len(keyword) % 2]}{{' |
| 4155 | + f'{["", " "][len(keyword) % 2]}do_something(); }}', |
| 4156 | + f'Controlled statements inside brackets of {keyword} clause' |
| 4157 | + f' should be on a separate line [whitespace/newline] [5]' |
| 4158 | + ) |
| 4159 | + |
| 4160 | + @parameterized.expand(['else', 'do', 'try']) |
| 4161 | + def testControlClauseWithoutParensNewline(self, keyword): |
| 4162 | + # The % 2 part is pseudorandom whitespace-support testing |
| 4163 | + self.TestLintContains( |
| 4164 | + f'{keyword}{["", " "][len(keyword) % 2]}{{' |
| 4165 | + f'{[" ", ""][len(keyword) % 2]}do_something(); }}', |
| 4166 | + f'Controlled statements inside brackets of {keyword} clause' |
| 4167 | + f' should be on a separate line [whitespace/newline] [5]' |
| 4168 | + ) |
| 4169 | + |
| 4170 | + def testControlClauseNewlineNameFalsePositives(self): |
| 4171 | + self.TestLint(' else if_condition_do_something();', '') |
| 4172 | + self.TestLint(' } else if (blah) {', '') |
| 4173 | + self.TestLint(' variable_ends_in_else = true;', '') |
| 4174 | + |
4144 | 4175 | def testTab(self): |
4145 | 4176 | self.TestLint('\tint a;', |
4146 | 4177 | 'Tab found; better to use spaces [whitespace/tab] [1]') |
|
0 commit comments