Skip to content

Commit 272ff50

Browse files
Merge pull request #415 from thk123/feature/lint-check-multi-line-function-call
Lint checks nested function calls broken over multiple lines
2 parents 60ec171 + 4d98b43 commit 272ff50

File tree

8 files changed

+320
-3
lines changed

8 files changed

+320
-3
lines changed

CODING_STANDARD

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Whitespaces:
1111
- For brackets, break after the bracket
1212
- In the case of function calls, put each argument on a separate line if
1313
they do not fit after one line break
14+
- Nested function calls do not need to be broken up into separate lines even
15+
if the outer function call does.
1416
- If a method is bigger than 50 lines, break it into parts.
1517
- Put matching { } into the same column.
1618
- No spaces around operators (=, +, ==, ...)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*******************************************************************\
2+
3+
Module: Lint Examples
4+
5+
Author: Thomas Kiley, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/*******************************************************************\
10+
11+
Function: fun
12+
13+
Inputs:
14+
15+
Outputs:
16+
17+
Purpose:
18+
19+
\*******************************************************************/
20+
21+
static void fun()
22+
{
23+
// Correct
24+
foo(
25+
x,
26+
y);
27+
28+
// Incorrect, x should be on the next line
29+
foo(x,
30+
y);
31+
32+
// Incorrect indent should be only 2
33+
foo(
34+
x,
35+
y);
36+
37+
// Correct
38+
int x=bar(
39+
x,
40+
y);
41+
42+
// Incorrect, x should be on the next line
43+
int x=bar(x,
44+
y);
45+
46+
// Incorrect indent should be only 2
47+
int x=bar(
48+
x,
49+
y);
50+
51+
// Correct
52+
*model=baz(
53+
x,
54+
y);
55+
56+
// Incorrect, x should be on the next line
57+
*model=baz(x,
58+
y);
59+
60+
// Incorrect indent should be only 2
61+
*model=baz(
62+
x,
63+
y);
64+
65+
// Correct
66+
var->fun(
67+
x,
68+
y);
69+
70+
// Incorrect, x should be on the next line
71+
var->fun(x,
72+
y);
73+
74+
// Incorrect indent should be only 2
75+
var->fun(
76+
x,
77+
y);
78+
79+
// Incorrect
80+
fun(
81+
x, y);
82+
83+
// Incorrect
84+
fun(
85+
x, y,
86+
z);
87+
}
88+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
main.cpp
3+
4+
^main\.cpp:29: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
5+
^main\.cpp:34: Indent of wrapped parenthesized expression or parameter or argument list should be 2 \[whitespace/indent\] \[4\]
6+
^main\.cpp:43: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
7+
^main\.cpp:48: Indent of wrapped parenthesized expression or parameter or argument list should be 2 \[whitespace/indent\] \[4\]
8+
^main\.cpp:57: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
9+
^main\.cpp:62: Indent of wrapped parenthesized expression or parameter or argument list should be 2 \[whitespace/indent\] \[4\]
10+
^main\.cpp:71: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
11+
^main\.cpp:76: Indent of wrapped parenthesized expression or parameter or argument list should be 2 \[whitespace/indent\] \[4\]
12+
^main\.cpp:81: If parameters or arguments require a line break, the closing bracket should be on the same line as the final parameter \[whitespace/indent\] \[4\]
13+
^main\.cpp:85: If parameters or arguments require a line break, each parameter should be put on its own line. \[whitespace/indent\] \[4\]
14+
^Total errors found: 10$
15+
^EXIT=1$
16+
^SIGNAL=0$
17+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*******************************************************************\
2+
3+
Module: Lint Examples
4+
5+
Author: Thomas Kiley, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/*******************************************************************\
10+
11+
Function: fun
12+
13+
Inputs:
14+
15+
Outputs:
16+
17+
Purpose:
18+
19+
\*******************************************************************/
20+
21+
static void fun()
22+
{
23+
// Incorrect, call should be on a new line
24+
nested(call(),
25+
another_param);
26+
27+
// Incorrect - should be indented by 2
28+
nested(
29+
call(),
30+
another_param);
31+
32+
// Correct
33+
nested(
34+
call(),
35+
another_param);
36+
37+
// Correct
38+
twice(
39+
nested(
40+
call(
41+
param1),
42+
param2),
43+
param3)
44+
45+
// Correct
46+
foo(
47+
bar(x, y),
48+
z);
49+
50+
// Correct
51+
foo(
52+
bar(
53+
x,
54+
y),
55+
z);
56+
57+
// Incorrect, the bar arguments have been split up therefore
58+
// they all should be split up
59+
foo(
60+
bar(x,
61+
y),
62+
z);
63+
64+
// Incorrect bar should be on the next line
65+
foo(bar(x, y),
66+
z);
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.cpp
3+
4+
^main\.cpp:24: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
5+
^main\.cpp:29: Indent of wrapped parenthesized expression or parameter or argument list should be 2 \[whitespace/indent\] \[4\]
6+
^main\.cpp:60: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
7+
^main\.cpp:65: If parameters or arguments require a line break, each parameter should be put on its own line\. \[whitespace/indent\] \[4\]
8+
^Total errors found: 4$
9+
^EXIT=1$
10+
^SIGNAL=0$
11+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************\
2+
3+
Module: Lint Examples
4+
5+
Author: Thomas Kiley, [email protected]
6+
7+
\*******************************************************************/
8+
9+
/*******************************************************************\
10+
11+
Function: fun
12+
13+
Inputs:
14+
15+
Outputs:
16+
17+
Purpose:
18+
19+
\*******************************************************************/
20+
21+
static void fun()
22+
{
23+
// Correct as for loop not function
24+
for(int x=0;
25+
x<10;
26+
++x)
27+
{}
28+
29+
// Correct as an if statement not a function
30+
if(a==b ||
31+
c==d)
32+
{
33+
do_something();
34+
}
35+
36+
// Correct as ranged based for loop not function
37+
for(x:
38+
list)
39+
{}
40+
41+
// Correct since if statement
42+
if(some_check(with, params)==
43+
some_value)
44+
{
45+
do_something();
46+
}
47+
48+
// Correct since if statement
49+
if(condition_a&&
50+
(condition_b||
51+
condition_c))
52+
{
53+
do_something();
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.cpp
3+
4+
^Total errors found: 0$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--

scripts/cpplint.py

+73-3
Original file line numberDiff line numberDiff line change
@@ -4687,9 +4687,79 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
46874687
if linenum>0:
46884688
while prev_initial_spaces < len(prev) and prev[prev_initial_spaces] == ' ':
46894689
prev_initial_spaces += 1
4690-
if Search(r'\([^\)]*,$', elided_line) or Search(r'\(\[^\)]*, $', elided_line):
4691-
error(filename, linenum, 'whitespace/indent', 4,
4692-
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4690+
# here a regex isn't sufficent we need a stack to match brackets
4691+
# because even an open bracket and a , at the end might just be function call
4692+
# as a parameter.
4693+
# Instead the rule we try to apply here is:
4694+
# - if we find an opening bracket, we find the matching closing bracket
4695+
# - if the bracket is on a different line we require all of the parameters to be on a separate line
4696+
# - if there is another opening bracket Skip to the closing bracket as will be checked in a subsequent line check
4697+
# - ignore the line if it is a for/if etc since rules are different
4698+
4699+
# Look for an opening bracket that doesn't have a semi-colon on the same line
4700+
bracket_search = Search(r'[\w_]+\s*(?P<bracket>\()[^;]*$', elided_line)
4701+
4702+
# Exclude the check if any of these keywords are present
4703+
# They could trip us up as they have different formatting rules to functions
4704+
keyword_search = Search(r'\b(if|for|while|catch|switch)\b', elided_line)
4705+
4706+
if bracket_search and not keyword_search:
4707+
open_bracket_pos = bracket_search.start('bracket')
4708+
close_line, close_linenum, close_pos = CloseExpression(clean_lines, linenum, open_bracket_pos)
4709+
if close_pos != -1:
4710+
# If the closing line is different from the opening line we need to
4711+
# verify that each of the parameters are on separate lines
4712+
if close_linenum != linenum:
4713+
# The first line needs to have no parameters on it
4714+
if(Search(r'\(+[^\(]+', elided_line)):
4715+
error(filename, linenum, 'whitespace/indent', 4,
4716+
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4717+
4718+
# For each line afer we need to verify it consists of exactly one parameter
4719+
# Except if we find an opening bracket - in this case we ignore everything until the closing
4720+
# bracket (any errors within these brackets will be picked up when we check this line)
4721+
start_linenum = linenum + 1
4722+
while(start_linenum < close_linenum):
4723+
arg_line = clean_lines.elided[start_linenum]
4724+
nested_bracket_search = Search('\(', arg_line)
4725+
if nested_bracket_search:
4726+
nested_open_bracket_pos = nested_bracket_search.start()
4727+
# Just because we are calling a nested function doesn't mean
4728+
# we allow multiple parameters on the line
4729+
if(Search(',', arg_line[:nested_open_bracket_pos])):
4730+
error(filename, start_linenum, 'whitespace/indent', 4,
4731+
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4732+
4733+
nested_close_line, nested_close_linenum, _ = CloseExpression(clean_lines, start_linenum, nested_open_bracket_pos)
4734+
4735+
# If anything other closing statements or commas appear there is another parameter after the nested call
4736+
if not Search(r'\)(,|\)|;)*', nested_close_line):
4737+
error(filename, start_linenum, 'whitespace/indent', 4,
4738+
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4739+
# Skip to the end of the bracket
4740+
start_linenum = nested_close_linenum
4741+
else:
4742+
if(not Match('^\s*[^,]+,$', arg_line)):
4743+
error(filename, start_linenum, 'whitespace/indent', 4,
4744+
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4745+
4746+
start_linenum+=1
4747+
# For the final line we also need to check one parameter on it
4748+
# e.g. we require bracket on same line as last parameter
4749+
# foo(
4750+
# x);
4751+
if not Search(r'^\s*[^,]+\)', close_line):
4752+
# If this is true, the we failed because we just had the close bracket
4753+
if Search(r'[^,]*\)', close_line):
4754+
error(filename, close_linenum, 'whitespace/indent', 4,
4755+
'If parameters or arguments require a line break, the closing bracket should be on the same line as the final parameter')
4756+
else:
4757+
# In this case the problem is we had a bracket
4758+
# i.e. more than one parameter on the last line
4759+
error(filename, close_linenum, 'whitespace/indent', 4,
4760+
'If parameters or arguments require a line break, each parameter should be put on its own line.')
4761+
4762+
46934763
if (Search(r'\([^\)]*$', elided_prev) and initial_spaces-2 != prev_initial_spaces) and not Search(r'for|while|if|;', elided_prev):
46944764
error(filename, linenum, 'whitespace/indent', 4,
46954765
'Indent of wrapped parenthesized expression or parameter or argument list should be 2')

0 commit comments

Comments
 (0)