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)
| 6179 | |
| 6180 | |
| 6181 | def CheckRedundantVirtual(filename, clean_lines, linenum, error): |
| 6182 | """Check if line contains a redundant "virtual" function-specifier. |
| 6183 | |
| 6184 | Args: |
| 6185 | filename: The name of the current file. |
| 6186 | clean_lines: A CleansedLines instance containing the file. |
| 6187 | linenum: The number of the line to check. |
| 6188 | error: The function to call with any errors found. |
| 6189 | """ |
| 6190 | # Look for "virtual" on current line. |
| 6191 | line = clean_lines.elided[linenum] |
| 6192 | virtual = Match(r'^(.*)(\bvirtual\b)(.*)$', line) |
| 6193 | if not virtual: return |
| 6194 | |
| 6195 | # Ignore "virtual" keywords that are near access-specifiers. These |
| 6196 | # are only used in class base-specifier and do not apply to member |
| 6197 | # functions. |
| 6198 | if (Search(r'\b(public|protected|private)\s+$', virtual.group(1)) or |
| 6199 | Match(r'^\s+(public|protected|private)\b', virtual.group(3))): |
| 6200 | return |
| 6201 | |
| 6202 | # Ignore the "virtual" keyword from virtual base classes. Usually |
| 6203 | # there is a column on the same line in these cases (virtual base |
| 6204 | # classes are rare in google3 because multiple inheritance is rare). |
| 6205 | if Match(r'^.*[^:]:[^:].*$', line): return |
| 6206 | |
| 6207 | # Look for the next opening parenthesis. This is the start of the |
| 6208 | # parameter list (possibly on the next line shortly after virtual). |
| 6209 | # TODO(unknown): doesn't work if there are virtual functions with |
| 6210 | # decltype() or other things that use parentheses, but csearch suggests |
| 6211 | # that this is rare. |
| 6212 | end_col = -1 |
| 6213 | end_line = -1 |
| 6214 | start_col = len(virtual.group(2)) |
| 6215 | for start_line in xrange(linenum, min(linenum + 3, clean_lines.NumLines())): |
| 6216 | line = clean_lines.elided[start_line][start_col:] |
| 6217 | parameter_list = Match(r'^([^(]*)\(', line) |
| 6218 | if parameter_list: |
| 6219 | # Match parentheses to find the end of the parameter list |
| 6220 | (_, end_line, end_col) = CloseExpression( |
| 6221 | clean_lines, start_line, start_col + len(parameter_list.group(1))) |
| 6222 | break |
| 6223 | start_col = 0 |
| 6224 | |
| 6225 | if end_col < 0: |
| 6226 | return # Couldn't find end of parameter list, give up |
| 6227 | |
| 6228 | # Look for "override" or "final" after the parameter list |
| 6229 | # (possibly on the next few lines). |
| 6230 | for i in xrange(end_line, min(end_line + 3, clean_lines.NumLines())): |
| 6231 | line = clean_lines.elided[i][end_col:] |
| 6232 | match = Search(r'\b(override|final)\b', line) |
| 6233 | if match: |
| 6234 | error(filename, linenum, 'readability/inheritance', 4, |
| 6235 | ('"virtual" is redundant since function is ' |
| 6236 | 'already declared as "%s"' % match.group(1))) |
| 6237 | |
| 6238 | # Set end_col to check whole lines after we are done with the |
no test coverage detected