@@ -1547,34 +1547,28 @@ def IsTemplateArgumentList_DB(clean_lines, linenum, pos):
1547
1547
1548
1548
return True
1549
1549
1550
- def OpenExpression (clean_lines , linenum , pos ):
1551
- """If input points to ) or } or ] or >, finds the position that opens it.
1552
-
1553
- If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1554
- linenum/pos that correspond to the closing of the expression.
1555
-
1556
- Essentially a mirror of what CloseExpression does
1550
+ def ForceOpenExpression (clean_lines , linenum , pos , bracket ):
1551
+ """Find an opening bracket matching the specified closing bracket
1557
1552
1558
- TODO(tkiley): could probably be merged with CloseExpression
1553
+ Search starting at the position for a matching closing bracket of the
1554
+ same type as bracket.
1559
1555
1560
1556
Args:
1561
1557
clean_lines: A CleansedLines instance containing the file.
1562
1558
linenum: The number of the line to check.
1563
1559
pos: A position on the line.
1560
+ bracket: The style of bracket to match
1564
1561
1565
1562
Returns:
1566
1563
A tuple (line, linenum, pos) pointer *to* the closing brace, or
1567
1564
(line, len(lines), -1) if we never find a close. Note we ignore
1568
1565
strings and comments when matching; and the line we return is the
1569
1566
'cleansed' line at linenum.
1570
1567
"""
1571
-
1572
1568
line = clean_lines .elided [linenum ]
1573
- if (line [pos ] not in ')}]>' ):
1574
- return (line , clean_lines .NumLines (), - 1 )
1575
1569
1576
1570
# Check first line
1577
- (end_pos , stack ) = FindStartOfExpressionInLine (line , pos , [])
1571
+ (end_pos , stack ) = FindStartOfExpressionInLine (line , pos , [bracket ])
1578
1572
if end_pos > - 1 :
1579
1573
return (line , linenum , end_pos )
1580
1574
@@ -1589,6 +1583,37 @@ def OpenExpression(clean_lines, linenum, pos):
1589
1583
# Did not find end of expression before end of file, give up
1590
1584
return (line , clean_lines .NumLines (), - 1 )
1591
1585
1586
+ def OpenExpression (clean_lines , linenum , pos ):
1587
+ """If input points to ) or } or ] or >, finds the position that opens it.
1588
+
1589
+ If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1590
+ linenum/pos that correspond to the closing of the expression.
1591
+
1592
+ Essentially a mirror of what CloseExpression does
1593
+
1594
+ Calls ForceOpenExpression with the bracket type pointed at
1595
+
1596
+ TODO(tkiley): could probably be merged with CloseExpression
1597
+
1598
+ Args:
1599
+ clean_lines: A CleansedLines instance containing the file.
1600
+ linenum: The number of the line to check.
1601
+ pos: A position on the line.
1602
+
1603
+ Returns:
1604
+ A tuple (line, linenum, pos) pointer *to* the closing brace, or
1605
+ (line, len(lines), -1) if we never find a close. Note we ignore
1606
+ strings and comments when matching; and the line we return is the
1607
+ 'cleansed' line at linenum.
1608
+ """
1609
+
1610
+ line = clean_lines .elided [linenum ]
1611
+ if (line [pos ] not in ')}]>' ):
1612
+ return (line , clean_lines .NumLines (), - 1 )
1613
+ else :
1614
+ return ForceOpenExpression (clean_lines , linenum , pos - 1 , line [pos ])
1615
+
1616
+
1592
1617
def FindEndOfExpressionInLine (line , startpos , stack ):
1593
1618
"""Find the position just after the end of current parenthesized expression.
1594
1619
@@ -3525,15 +3550,12 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3525
3550
# Otherwise not. Note we only check for non-spaces on *both* sides;
3526
3551
# sometimes people put non-spaces on one side when aligning ='s among
3527
3552
# many lines (not that this is behavior that I approve of...)
3528
- match1 = Search (r'[^\s]+[\s](=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|\^|\+[^\+]|\/)' , line )
3529
- match2 = Search (r'(=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|!|\^|\+|\/)[\s]' , line )
3530
- operator_pos , op_end = match1 .span (1 ) if match1 else (- 1 , - 1 )
3531
- operator_pos2 , op_end2 = match2 .span (1 ) if match2 else (- 1 , - 1 )
3553
+ left_hand_space_match = Search (r'[^\s]+[\s](=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|\^|\+[^\+]|\/)' , line )
3554
+ right_hand_space_match = Search (r'(=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|!|\^|\+|\/)[\s]' , line )
3555
+ operator_pos , op_end = left_hand_space_match .span (1 ) if left_hand_space_match else (- 1 , - 1 )
3556
+ operator_pos2 , op_end2 = right_hand_space_match .span (1 ) if right_hand_space_match else (- 1 , - 1 )
3532
3557
3533
- if match2 and match2 .group (1 ) == '>' :
3534
- res = IsTemplateArgumentList_DB (clean_lines , linenum , operator_pos2 )
3535
-
3536
- if (match1 and
3558
+ if (left_hand_space_match and
3537
3559
not Search (r'<<' , line ) and # We ignore the left shift operator since might be a stream and then formatting rules go out of the window
3538
3560
not Search (r'char \*' , line ) and # I don't know why this exception exists?
3539
3561
not Search (r'\#include' , line ) and # I suppose file names could contains operators??
@@ -3545,12 +3567,12 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3545
3567
# and not Search(r'operator=', line)):
3546
3568
error (filename , linenum , 'whitespace/operators' , 4 ,
3547
3569
# 'Missing spaces around =')
3548
- 'Remove spaces around %s' % match1 .group (1 ))
3549
- elif (match2 and
3570
+ 'Remove spaces around %s' % left_hand_space_match .group (1 ))
3571
+ elif (right_hand_space_match and
3550
3572
not Search (r'<<' , line ) and
3551
3573
not IsTemplateArgumentList_DB (clean_lines , linenum , operator_pos2 )):
3552
3574
error (filename , linenum , 'whitespace/operators' , 4 ,
3553
- 'Remove spaces around %s' % match2 .group (0 ))
3575
+ 'Remove spaces around %s' % right_hand_space_match .group (0 ))
3554
3576
3555
3577
# these would cause too many false alarms if we checked for one-sided spaces only
3556
3578
match = Search (r'\s(-|\*)(\s|$)' , line )
@@ -3562,10 +3584,16 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3562
3584
if Search (r'(struct|class)\s[\w_]*\s+:' , line ):
3563
3585
error (filename , linenum , 'readability/identifiers' , 4 , 'There shouldn\' t be a space between class identifier and :' )
3564
3586
3565
- #check type definitions end with t
3566
- if Search (r'(struct|class)\s[\w_]*[^t^;^:^\s](;$|\s|:|$)' , line ) and not Search (r'^template <' , line ) and not Search (r'^template<' , line ):
3567
- error (filename , linenum , 'readability/identifiers' , 4 ,
3568
- 'Class or struct identifier should end with t' )
3587
+ #check type definitions end with t
3588
+ # Look for class declarations and check the final character is a t
3589
+ # Exclude classes in side template argument lists (why?)
3590
+ class_name_match = Search (r'\b(struct|class)\s(?P<class_name>[\w_]+)' , line )
3591
+ if class_name_match :
3592
+ class_name = class_name_match .group ('class_name' )
3593
+ if not class_name .endswith ('t' ):
3594
+ if not Search (r'\btemplate <' , line ) and not Search (r'\btemplate<' , line ):
3595
+ error (filename , linenum , 'readability/identifiers' , 4 ,
3596
+ 'Class or struct identifier should end with t' )
3569
3597
3570
3598
if Search (r'(struct|class)\s[\w_]*_t(;$|\s|:|$)' , line ):
3571
3599
error (filename , linenum , 'readability/identifiers' , 4 ,
@@ -3630,17 +3658,6 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3630
3658
# error(filename, linenum, 'whitespace/operators', 3,
3631
3659
# 'Missing spaces around >')
3632
3660
3633
- # We allow no-spaces around << when used like this: 10<<20, but
3634
- # not otherwise (particularly, not when used as streams)
3635
- #
3636
- # We also allow operators following an opening parenthesis, since
3637
- # those tend to be macros that deal with operators.
3638
- match = Search (r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])' , line )
3639
- if (match and not (match .group (1 ).isdigit () and match .group (2 ).isdigit ()) and
3640
- not (match .group (1 ) == 'operator' and match .group (2 ) == ';' )):
3641
- error (filename , linenum , 'whitespace/operators' , 3 ,
3642
- 'Missing spaces around <<' )
3643
-
3644
3661
# We allow no-spaces around >> for almost anything. This is because
3645
3662
# C++11 allows ">>" to close nested templates, which accounts for
3646
3663
# most cases when ">>" is not followed by a space.
@@ -3664,6 +3681,48 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3664
3681
error (filename , linenum , 'whitespace/operators' , 4 ,
3665
3682
'Extra space for operator %s' % match .group (1 ))
3666
3683
3684
+ def CheckPointerReferenceSpacing (filename , clean_lines , linenum , error ):
3685
+ """Checks the */& are attached to variable names rather than types
3686
+
3687
+ A pointer or reference type should have the */& attached to the variable
3688
+ name rather than the type. I.e. a pointer to an int should be:
3689
+
3690
+ int *var_name;
3691
+
3692
+ Args:
3693
+ filename: The name of the current file.
3694
+ clean_lines: A CleansedLines instance containing the file.
3695
+ linenum: The number of the line to check.
3696
+ error: The function to call with any errors found.
3697
+ """
3698
+ line = clean_lines .elided [linenum ]
3699
+
3700
+ # Find types by looking for word_names that are at the start of the line
3701
+ # If there are followed by a * or & (after an optional ' const')
3702
+ # then they appear to be a reference/pointer type with it attached to
3703
+ # the type rather than the variable
3704
+ wrong_type_match = Search (r'^\s*([\w_])+( const)?(?P<type>[&\*])\s*\w' , line )
3705
+
3706
+ if wrong_type_match :
3707
+ # This still could be a false positive, we must
3708
+ # check that we are not inside brackets as then could be just be
3709
+ # operators (multiply and logical AND)
3710
+ pos = wrong_type_match .start (1 )
3711
+ _ , _ , opening_pos = ForceOpenExpression (clean_lines , linenum , pos , ')' )
3712
+
3713
+ # If we don't find a matching close brace then we aren't in brackets
3714
+ # so can assume this is a type with the * or & attached to it
3715
+ if opening_pos == - 1 :
3716
+ op_type = wrong_type_match .group ('type' )
3717
+ op_word = ""
3718
+ if op_type == '*' :
3719
+ op_word = 'Pointer'
3720
+ else :
3721
+ op_word = 'Reference'
3722
+ error (filename , linenum , 'whitespace/operators' , 4 ,
3723
+ op_word + ' type name must have ' + op_type + ' attached to the type name' )
3724
+
3725
+
3667
3726
3668
3727
def CheckParenthesisSpacing (filename , clean_lines , linenum , error ):
3669
3728
"""Checks for horizontal spacing around parentheses.
@@ -4679,6 +4738,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4679
4738
CheckAccess (filename , clean_lines , linenum , nesting_state , error )
4680
4739
CheckSpacing (filename , clean_lines , linenum , nesting_state , error )
4681
4740
CheckOperatorSpacing (filename , clean_lines , linenum , error )
4741
+ CheckPointerReferenceSpacing (filename , clean_lines , linenum , error )
4682
4742
CheckParenthesisSpacing (filename , clean_lines , linenum , error )
4683
4743
CheckCommaSpacing (filename , clean_lines , linenum , error )
4684
4744
CheckBracesSpacing (filename , clean_lines , linenum , nesting_state , error )
@@ -5088,8 +5148,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
5088
5148
break
5089
5149
if not is_const :
5090
5150
error (filename , linenum , 'runtime/arrays' , 1 ,
5091
- 'Do not use variable-length arrays. Use an appropriately named '
5092
- "('k' followed by CamelCase) compile-time constant for the size." )
5151
+ 'Do not use variable-length arrays.' )
5093
5152
5094
5153
# Check for use of unnamed namespaces in header files. Registration
5095
5154
# macros are typically OK, so we allow use of "namespace {" on lines
0 commit comments