@@ -3230,7 +3230,17 @@ class _WrappedInfo(_BlockInfo):
32303230class _MemInitListInfo (_WrappedInfo ):
32313231 """Stores information about member initializer lists."""
32323232
3233- pass
3233+ def __init__ (self , linenum ):
3234+ _WrappedInfo .__init__ (self , linenum , False )
3235+ # For `: a(b)`, a is the identifier
3236+ self .expecting_identifier = True
3237+ # Whether we are expecting the value that follows the identifier
3238+ self .expecting_braces = False
3239+ # Whether we are currently within braces
3240+ self .in_braces = False
3241+ # Only used when within braces
3242+ self .is_curly = False
3243+ self .open_brace_count = 0
32343244
32353245
32363246class _PreprocessorInfo :
@@ -3384,6 +3394,20 @@ def InTemplateArgumentList(self, clean_lines, linenum, pos):
33843394 pos = end_pos
33853395 return False
33863396
3397+ def _BequeathParensAndAppend (self , appendee : _BlockInfo , parens_changed : int ):
3398+ """Pass down number of open parentheses and append to the stack.
3399+
3400+ Args:
3401+ appendee: The object to append to the stack.
3402+ parens_changed: The number of parentheses opened, as computed by _ChangeParentheses().
3403+ """
3404+ # Compensate for adding parentheses to the previous top block before this update
3405+ if self .stack :
3406+ self .stack [- 1 ].open_parentheses -= parens_changed
3407+ appendee .open_parentheses += parens_changed
3408+
3409+ self .stack .append (appendee )
3410+
33873411 def UpdatePreprocessor (self , line ):
33883412 """Update preprocessor stack.
33893413
@@ -3444,9 +3468,15 @@ def _Pop(self):
34443468 """Pop the innermost state (top of the stack) and remember the popped item."""
34453469 self .popped_top = self .stack .pop ()
34463470
3447- def _CountOpenParentheses (self , line : str ):
3448- # Count parentheses. This is to avoid adding struct arguments to
3449- # the nesting stack.
3471+ def _ChangeParentheses (self , line : str ) -> int :
3472+ """
3473+ Count parentheses. This is to avoid adding struct arguments to the nesting stack.
3474+ Args:
3475+ line: The line to count parentheses on.
3476+
3477+ Returns:
3478+ The number of parentheses opened on this line.
3479+ """
34503480 if self .stack :
34513481 inner_block = self .stack [- 1 ]
34523482 depth_change = line .count ("(" ) - line .count (")" )
@@ -3469,7 +3499,10 @@ def _CountOpenParentheses(self, line: str):
34693499 # Exit assembly block
34703500 inner_block .inline_asm = _END_ASM
34713501
3472- def _UpdateNamesapce (self , line : str , linenum : int ) -> str | None :
3502+ return depth_change
3503+ return 0
3504+
3505+ def _ConsumeNamespace (self , line : str , linenum : int ) -> str | None :
34733506 """
34743507 Match start of namespace, append to stack, and consume line
34753508 Args:
@@ -3496,21 +3529,29 @@ def _UpdateNamesapce(self, line: str, linenum: int) -> str | None:
34963529 line = line [line .find ("{" ) + 1 :]
34973530 return line
34983531
3499- def _UpdateConstructor (self , line : str , linenum : int , class_name : str | None = None ):
3532+ def _UpdateConstructor (
3533+ self , line : str , linenum : int , parens_changed : int , class_name : str | None = None
3534+ ) -> bool :
35003535 """
35013536 Check if the given line is a constructor.
35023537 Args:
35033538 line: Line to check.
35043539 class_name: If line checked is inside of a class block, a str of the class's name;
35053540 otherwise, None.
3541+ parens_changed: The number of parentheses opened on this line.
3542+
3543+ Returns:
3544+ Whether the given line was a constructor.
35063545 """
3546+ prefix = r"(?:^|public|private|protected|friend|inline|explicit|constexpr)\s*"
35073547 if not class_name :
3508- if not re .match ( r"\s* (\w*)\s*::\s*\1\s*\(" , line ):
3509- return
3510- elif not re .match ( rf"\s* { re .escape (class_name )} \s*\(" , line ):
3511- return
3548+ if not re .search ( prefix + r" (\w*)\s*::\s*\1\s*\(" , line ):
3549+ return False
3550+ elif not re .search ( prefix + rf"{ re .escape (class_name )} \s*\(" , line ):
3551+ return False
35123552
3513- self .stack .append (_ConstructorInfo (linenum ))
3553+ self ._BequeathParensAndAppend (_ConstructorInfo (linenum ))
3554+ return True
35143555
35153556 # TODO(google): Update() is too long, but we will refactor later.
35163557 def Update (self , filename : str , clean_lines : CleansedLines , linenum : int , error ):
@@ -3538,12 +3579,12 @@ def Update(self, filename: str, clean_lines: CleansedLines, linenum: int, error)
35383579 # Update pp_stack
35393580 self .UpdatePreprocessor (line )
35403581
3541- self ._CountOpenParentheses (line )
3582+ parens_changed = self ._ChangeParentheses (line )
35423583
35433584 # Consume namespace declaration at the beginning of the line. Do
35443585 # this in a loop so that we catch same line declarations like this:
35453586 # namespace proto2 { namespace bridge { class MessageSet; } }
3546- while (new_line := self ._UpdateNamesapce (line , linenum )) is not None : # could be empty str
3587+ while (new_line := self ._ConsumeNamespace (line , linenum )) is not None : # could be empty str
35473588 line = new_line
35483589
35493590 # Look for a class declaration in whatever is left of the line
@@ -3616,8 +3657,11 @@ def Update(self, filename: str, clean_lines: CleansedLines, linenum: int, error)
36163657 line = access_match .group (4 )
36173658 else :
36183659 self ._UpdateConstructor (line , linenum , class_name = classinfo .name )
3660+ self ._UpdateConstructor (
3661+ line , linenum , parens_changed , class_name = classinfo .name
3662+ )
36193663 else : # Not in class
3620- self ._UpdateConstructor (line , linenum )
3664+ self ._UpdateConstructor (line , linenum , parens_changed )
36213665
36223666 # If brace not open and we just finished a parenthetical definition,
36233667 # check if we're in a member initializer list following a constructor.
@@ -3630,16 +3674,16 @@ def Update(self, filename: str, clean_lines: CleansedLines, linenum: int, error)
36303674 and not self .stack [- 1 ].seen_open_brace
36313675 and re .search (r"[^:]:[^:]" , line )
36323676 ):
3633- self .stack . append (_MemInitListInfo (linenum , seen_open_brace = False ) )
3677+ self ._BequeathParensAndAppend (_MemInitListInfo (linenum ), parens_changed )
36343678
36353679 # Consume braces or semicolons from what's left of the line
36363680 while True :
36373681 # Match first brace, semicolon, or closed parenthesis.
3638- matched = re .match (r"^[^{;)}]* ([{;)}])(.*)$ " , line )
3639- if not matched :
3682+ searched = re .search (r"([{;)}])" , line )
3683+ if not searched :
36403684 break
36413685
3642- token = matched .group (1 )
3686+ token = searched .group (1 )
36433687 if token == "{" :
36443688 # If namespace or class hasn't seen an opening brace yet, mark
36453689 # namespace/class head as complete. Push a new block onto the
@@ -3677,7 +3721,7 @@ def Update(self, filename: str, clean_lines: CleansedLines, linenum: int, error)
36773721 if self .stack :
36783722 self .stack [- 1 ].CheckEnd (filename , clean_lines , linenum , error )
36793723 self ._Pop ()
3680- line = matched . group ( 2 )
3724+ line = line [ searched . end ( 0 ) :]
36813725
36823726 def InnermostClass (self ):
36833727 """Get class info on the top of the stack.
@@ -7294,15 +7338,22 @@ def ShouldCheckNamespaceIndentation(
72947338
72957339 # Skip if we are extra-indenting a member initializer list.
72967340 if (
7297- isinstance (nesting_state .previous_stack_top , _ConstructorInfo ) # F/N (A::A() : _a(0) {/{})
7298- and (
7299- isinstance (nesting_state .stack [- 1 ], _MemInitListInfo )
7300- or isinstance (nesting_state .popped_top , _MemInitListInfo )
7341+ (
7342+ isinstance (nesting_state .previous_stack_top , _ConstructorInfo ) # F/N (A::A() : _a(0){)
7343+ and (
7344+ isinstance (nesting_state .stack [- 1 ], _MemInitListInfo )
7345+ or isinstance (nesting_state .popped_top , _MemInitListInfo )
7346+ )
7347+ )
7348+ or ( # empty constructor in multiline list
7349+ isinstance (nesting_state .previous_stack_top , _MemInitListInfo )
7350+ and isinstance (nesting_state .popped_top , _ConstructorInfo )
7351+ )
7352+ or ( # popping constructor after MemInitList on the same line (: _a(a) {})
7353+ isinstance (nesting_state .previous_stack_top , _ConstructorInfo )
7354+ and isinstance (nesting_state .popped_top , _ConstructorInfo )
7355+ and re .search (r"[^:]:[^:]" , raw_lines_no_comments [linenum ])
73017356 )
7302- ) or ( # popping constructor after MemInitList on the same line (: _a(a) {})
7303- isinstance (nesting_state .previous_stack_top , _ConstructorInfo )
7304- and isinstance (nesting_state .popped_top , _ConstructorInfo )
7305- and re .search (r"[^:]:[^:]" , raw_lines_no_comments [linenum ])
73067357 ):
73077358 return False
73087359
0 commit comments