Update nesting state with current line. Args: filename: The name of the current file. clean_lines: A CleansedLines instance containing the file. linenum: The number of the line to check. error: The function to call with any errors found.
(self, filename: str, clean_lines: CleansedLines, linenum: int, error)
| 3471 | |
| 3472 | # TODO(google): Update() is too long, but we will refactor later. |
| 3473 | def Update(self, filename: str, clean_lines: CleansedLines, linenum: int, error): |
| 3474 | """Update nesting state with current line. |
| 3475 | |
| 3476 | Args: |
| 3477 | filename: The name of the current file. |
| 3478 | clean_lines: A CleansedLines instance containing the file. |
| 3479 | linenum: The number of the line to check. |
| 3480 | error: The function to call with any errors found. |
| 3481 | """ |
| 3482 | line = clean_lines.elided[linenum] |
| 3483 | |
| 3484 | # Remember top of the previous nesting stack. |
| 3485 | # |
| 3486 | # The stack is always pushed/popped and not modified in place, so |
| 3487 | # we can just do a shallow copy instead of copy.deepcopy. Using |
| 3488 | # deepcopy would slow down cpplint by ~28%. |
| 3489 | if self.stack: |
| 3490 | self.previous_stack_top = self.stack[-1] |
| 3491 | self.previous_open_parentheses = self.stack[-1].open_parentheses |
| 3492 | else: |
| 3493 | self.previous_stack_top = None |
| 3494 | |
| 3495 | # Update pp_stack |
| 3496 | self.UpdatePreprocessor(line) |
| 3497 | |
| 3498 | self._CountOpenParentheses(line) |
| 3499 | |
| 3500 | # Consume namespace declaration at the beginning of the line. Do |
| 3501 | # this in a loop so that we catch same line declarations like this: |
| 3502 | # namespace proto2 { namespace bridge { class MessageSet; } } |
| 3503 | while (new_line := self._UpdateNamesapce(line, linenum)) is not None: # could be empty str |
| 3504 | line = new_line |
| 3505 | |
| 3506 | # Look for a class declaration in whatever is left of the line |
| 3507 | # after parsing namespaces. The regexp accounts for decorated classes |
| 3508 | # such as in: |
| 3509 | # class LOCKABLE API Object { |
| 3510 | # }; |
| 3511 | class_decl_match = re.match( |
| 3512 | r"^(\s*(?:template\s*<[\w\s<>,:=]*>\s*)?" |
| 3513 | r"(class|struct)\s+(?:[a-zA-Z0-9_]+\s+)*(\w+(?:::\w+)*))" |
| 3514 | r"(.*)$", |
| 3515 | line, |
| 3516 | ) |
| 3517 | if class_decl_match and (not self.stack or self.stack[-1].open_parentheses == 0): |
| 3518 | # We do not want to accept classes that are actually template arguments: |
| 3519 | # template <class Ignore1, |
| 3520 | # class Ignore2 = Default<Args>, |
| 3521 | # template <Args> class Ignore3> |
| 3522 | # void Function() {}; |
| 3523 | # |
| 3524 | # To avoid template argument cases, we scan forward and look for |
| 3525 | # an unmatched '>'. If we see one, assume we are inside a |
| 3526 | # template argument list. |
| 3527 | end_declaration = len(class_decl_match.group(1)) |
| 3528 | if not self.InTemplateArgumentList(clean_lines, linenum, end_declaration): |
| 3529 | self.stack.append( |
| 3530 | _ClassInfo( |