Check if line contains a redundant "virtual" function-specifier. 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.
(filename, clean_lines, linenum, error)
| 7207 | |
| 7208 | |
| 7209 | def CheckRedundantVirtual(filename, clean_lines, linenum, error): |
| 7210 | """Check if line contains a redundant "virtual" function-specifier. |
| 7211 | |
| 7212 | Args: |
| 7213 | filename: The name of the current file. |
| 7214 | clean_lines: A CleansedLines instance containing the file. |
| 7215 | linenum: The number of the line to check. |
| 7216 | error: The function to call with any errors found. |
| 7217 | """ |
| 7218 | # Look for "virtual" on current line. |
| 7219 | line = clean_lines.elided[linenum] |
| 7220 | virtual = re.match(r"^(.*)(\bvirtual\b)(.*)$", line) |
| 7221 | if not virtual: |
| 7222 | return |
| 7223 | |
| 7224 | # Ignore "virtual" keywords that are near access-specifiers. These |
| 7225 | # are only used in class base-specifier and do not apply to member |
| 7226 | # functions. |
| 7227 | if re.search(r"\b(public|protected|private)\s+$", virtual.group(1)) or re.match( |
| 7228 | r"^\s+(public|protected|private)\b", virtual.group(3) |
| 7229 | ): |
| 7230 | return |
| 7231 | |
| 7232 | # Ignore the "virtual" keyword from virtual base classes. Usually |
| 7233 | # there is a column on the same line in these cases (virtual base |
| 7234 | # classes are rare in google3 because multiple inheritance is rare). |
| 7235 | if re.match(r"^.*[^:]:[^:].*$", line): |
| 7236 | return |
| 7237 | |
| 7238 | # Look for the next opening parenthesis. This is the start of the |
| 7239 | # parameter list (possibly on the next line shortly after virtual). |
| 7240 | # TODO(google): doesn't work if there are virtual functions with |
| 7241 | # decltype() or other things that use parentheses, but csearch suggests |
| 7242 | # that this is rare. |
| 7243 | end_col = -1 |
| 7244 | end_line = -1 |
| 7245 | start_col = len(virtual.group(2)) |
| 7246 | for start_line in range(linenum, min(linenum + 3, clean_lines.NumLines())): |
| 7247 | line = clean_lines.elided[start_line][start_col:] |
| 7248 | parameter_list = re.match(r"^([^(]*)\(", line) |
| 7249 | if parameter_list: |
| 7250 | # Match parentheses to find the end of the parameter list |
| 7251 | (_, end_line, end_col) = CloseExpression( |
| 7252 | clean_lines, start_line, start_col + len(parameter_list.group(1)) |
| 7253 | ) |
| 7254 | break |
| 7255 | start_col = 0 |
| 7256 | |
| 7257 | if end_col < 0: |
| 7258 | return # Couldn't find end of parameter list, give up |
| 7259 | |
| 7260 | # Look for "override" or "final" after the parameter list |
| 7261 | # (possibly on the next few lines). |
| 7262 | for i in range(end_line, min(end_line + 3, clean_lines.NumLines())): |
| 7263 | line = clean_lines.elided[i][end_col:] |
| 7264 | match = re.search(r"\b(override|final)\b", line) |
| 7265 | if match: |
| 7266 | error( |
no test coverage detected
searching dependent graphs…