| @@ 4142-4243 (lines=102) @@ | ||
| 4139 | "You don't need a ; after a }") |
|
| 4140 | ||
| 4141 | ||
| 4142 | def CheckEmptyBlockBody(filename, clean_lines, linenum, error): |
|
| 4143 | """Look for empty loop/conditional body with only a single semicolon. |
|
| 4144 | ||
| 4145 | Args: |
|
| 4146 | filename: The name of the current file. |
|
| 4147 | clean_lines: A CleansedLines instance containing the file. |
|
| 4148 | linenum: The number of the line to check. |
|
| 4149 | error: The function to call with any errors found. |
|
| 4150 | """ |
|
| 4151 | ||
| 4152 | # Search for loop keywords at the beginning of the line. Because only |
|
| 4153 | # whitespaces are allowed before the keywords, this will also ignore most |
|
| 4154 | # do-while-loops, since those lines should start with closing brace. |
|
| 4155 | # |
|
| 4156 | # We also check "if" blocks here, since an empty conditional block |
|
| 4157 | # is likely an error. |
|
| 4158 | line = clean_lines.elided[linenum] |
|
| 4159 | matched = Match(r'\s*(for|while|if)\s*\(', line) |
|
| 4160 | if matched: |
|
| 4161 | # Find the end of the conditional expression. |
|
| 4162 | (end_line, end_linenum, end_pos) = CloseExpression( |
|
| 4163 | clean_lines, linenum, line.find('(')) |
|
| 4164 | ||
| 4165 | # Output warning if what follows the condition expression is a semicolon. |
|
| 4166 | # No warning for all other cases, including whitespace or newline, since we |
|
| 4167 | # have a separate check for semicolons preceded by whitespace. |
|
| 4168 | if end_pos >= 0 and Match(r';', end_line[end_pos:]): |
|
| 4169 | if matched.group(1) == 'if': |
|
| 4170 | error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, |
|
| 4171 | 'Empty conditional bodies should use {}') |
|
| 4172 | else: |
|
| 4173 | error(filename, end_linenum, 'whitespace/empty_loop_body', 5, |
|
| 4174 | 'Empty loop bodies should use {} or continue') |
|
| 4175 | ||
| 4176 | # Check for if statements that have completely empty bodies (no comments) |
|
| 4177 | # and no else clauses. |
|
| 4178 | if end_pos >= 0 and matched.group(1) == 'if': |
|
| 4179 | # Find the position of the opening { for the if statement. |
|
| 4180 | # Return without logging an error if it has no brackets. |
|
| 4181 | opening_linenum = end_linenum |
|
| 4182 | opening_line_fragment = end_line[end_pos:] |
|
| 4183 | # Loop until EOF or find anything that's not whitespace or opening {. |
|
| 4184 | while not Search(r'^\s*\{', opening_line_fragment): |
|
| 4185 | if Search(r'^(?!\s*$)', opening_line_fragment): |
|
| 4186 | # Conditional has no brackets. |
|
| 4187 | return |
|
| 4188 | opening_linenum += 1 |
|
| 4189 | if opening_linenum == len(clean_lines.elided): |
|
| 4190 | # Couldn't find conditional's opening { or any code before EOF. |
|
| 4191 | return |
|
| 4192 | opening_line_fragment = clean_lines.elided[opening_linenum] |
|
| 4193 | # Set opening_line (opening_line_fragment may not be entire opening line). |
|
| 4194 | opening_line = clean_lines.elided[opening_linenum] |
|
| 4195 | ||
| 4196 | # Find the position of the closing }. |
|
| 4197 | opening_pos = opening_line_fragment.find('{') |
|
| 4198 | if opening_linenum == end_linenum: |
|
| 4199 | # We need to make opening_pos relative to the start of the entire line. |
|
| 4200 | opening_pos += end_pos |
|
| 4201 | (closing_line, closing_linenum, closing_pos) = CloseExpression( |
|
| 4202 | clean_lines, opening_linenum, opening_pos) |
|
| 4203 | if closing_pos < 0: |
|
| 4204 | return |
|
| 4205 | ||
| 4206 | # Now construct the body of the conditional. This consists of the portion |
|
| 4207 | # of the opening line after the {, all lines until the closing line, |
|
| 4208 | # and the portion of the closing line before the }. |
|
| 4209 | if (clean_lines.raw_lines[opening_linenum] != |
|
| 4210 | CleanseComments(clean_lines.raw_lines[opening_linenum])): |
|
| 4211 | # Opening line ends with a comment, so conditional isn't empty. |
|
| 4212 | return |
|
| 4213 | if closing_linenum > opening_linenum: |
|
| 4214 | # Opening line after the {. Ignore comments here since we checked above. |
|
| 4215 | bodylist = list(opening_line[opening_pos+1:]) |
|
| 4216 | # All lines until closing line, excluding closing line, with comments. |
|
| 4217 | bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) |
|
| 4218 | # Closing line before the }. Won't (and can't) have comments. |
|
| 4219 | bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1]) |
|
| 4220 | body = '\n'.join(bodylist) |
|
| 4221 | else: |
|
| 4222 | # If statement has brackets and fits on a single line. |
|
| 4223 | body = opening_line[opening_pos+1:closing_pos-1] |
|
| 4224 | ||
| 4225 | # Check if the body is empty |
|
| 4226 | if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body): |
|
| 4227 | return |
|
| 4228 | # The body is empty. Now make sure there's not an else clause. |
|
| 4229 | current_linenum = closing_linenum |
|
| 4230 | current_line_fragment = closing_line[closing_pos:] |
|
| 4231 | # Loop until EOF or find anything that's not whitespace or else clause. |
|
| 4232 | while Search(r'^\s*$|^(?=\s*else)', current_line_fragment): |
|
| 4233 | if Search(r'^(?=\s*else)', current_line_fragment): |
|
| 4234 | # Found an else clause, so don't log an error. |
|
| 4235 | return |
|
| 4236 | current_linenum += 1 |
|
| 4237 | if current_linenum == len(clean_lines.elided): |
|
| 4238 | break |
|
| 4239 | current_line_fragment = clean_lines.elided[current_linenum] |
|
| 4240 | ||
| 4241 | # The body is empty and there's no else clause until EOF or other code. |
|
| 4242 | error(filename, end_linenum, 'whitespace/empty_if_body', 4, |
|
| 4243 | ('If statement had no body and no else clause')) |
|
| 4244 | ||
| 4245 | ||
| 4246 | def FindCheckMacro(line): |
|
| @@ 4142-4243 (lines=102) @@ | ||
| 4139 | "You don't need a ; after a }") |
|
| 4140 | ||
| 4141 | ||
| 4142 | def CheckEmptyBlockBody(filename, clean_lines, linenum, error): |
|
| 4143 | """Look for empty loop/conditional body with only a single semicolon. |
|
| 4144 | ||
| 4145 | Args: |
|
| 4146 | filename: The name of the current file. |
|
| 4147 | clean_lines: A CleansedLines instance containing the file. |
|
| 4148 | linenum: The number of the line to check. |
|
| 4149 | error: The function to call with any errors found. |
|
| 4150 | """ |
|
| 4151 | ||
| 4152 | # Search for loop keywords at the beginning of the line. Because only |
|
| 4153 | # whitespaces are allowed before the keywords, this will also ignore most |
|
| 4154 | # do-while-loops, since those lines should start with closing brace. |
|
| 4155 | # |
|
| 4156 | # We also check "if" blocks here, since an empty conditional block |
|
| 4157 | # is likely an error. |
|
| 4158 | line = clean_lines.elided[linenum] |
|
| 4159 | matched = Match(r'\s*(for|while|if)\s*\(', line) |
|
| 4160 | if matched: |
|
| 4161 | # Find the end of the conditional expression. |
|
| 4162 | (end_line, end_linenum, end_pos) = CloseExpression( |
|
| 4163 | clean_lines, linenum, line.find('(')) |
|
| 4164 | ||
| 4165 | # Output warning if what follows the condition expression is a semicolon. |
|
| 4166 | # No warning for all other cases, including whitespace or newline, since we |
|
| 4167 | # have a separate check for semicolons preceded by whitespace. |
|
| 4168 | if end_pos >= 0 and Match(r';', end_line[end_pos:]): |
|
| 4169 | if matched.group(1) == 'if': |
|
| 4170 | error(filename, end_linenum, 'whitespace/empty_conditional_body', 5, |
|
| 4171 | 'Empty conditional bodies should use {}') |
|
| 4172 | else: |
|
| 4173 | error(filename, end_linenum, 'whitespace/empty_loop_body', 5, |
|
| 4174 | 'Empty loop bodies should use {} or continue') |
|
| 4175 | ||
| 4176 | # Check for if statements that have completely empty bodies (no comments) |
|
| 4177 | # and no else clauses. |
|
| 4178 | if end_pos >= 0 and matched.group(1) == 'if': |
|
| 4179 | # Find the position of the opening { for the if statement. |
|
| 4180 | # Return without logging an error if it has no brackets. |
|
| 4181 | opening_linenum = end_linenum |
|
| 4182 | opening_line_fragment = end_line[end_pos:] |
|
| 4183 | # Loop until EOF or find anything that's not whitespace or opening {. |
|
| 4184 | while not Search(r'^\s*\{', opening_line_fragment): |
|
| 4185 | if Search(r'^(?!\s*$)', opening_line_fragment): |
|
| 4186 | # Conditional has no brackets. |
|
| 4187 | return |
|
| 4188 | opening_linenum += 1 |
|
| 4189 | if opening_linenum == len(clean_lines.elided): |
|
| 4190 | # Couldn't find conditional's opening { or any code before EOF. |
|
| 4191 | return |
|
| 4192 | opening_line_fragment = clean_lines.elided[opening_linenum] |
|
| 4193 | # Set opening_line (opening_line_fragment may not be entire opening line). |
|
| 4194 | opening_line = clean_lines.elided[opening_linenum] |
|
| 4195 | ||
| 4196 | # Find the position of the closing }. |
|
| 4197 | opening_pos = opening_line_fragment.find('{') |
|
| 4198 | if opening_linenum == end_linenum: |
|
| 4199 | # We need to make opening_pos relative to the start of the entire line. |
|
| 4200 | opening_pos += end_pos |
|
| 4201 | (closing_line, closing_linenum, closing_pos) = CloseExpression( |
|
| 4202 | clean_lines, opening_linenum, opening_pos) |
|
| 4203 | if closing_pos < 0: |
|
| 4204 | return |
|
| 4205 | ||
| 4206 | # Now construct the body of the conditional. This consists of the portion |
|
| 4207 | # of the opening line after the {, all lines until the closing line, |
|
| 4208 | # and the portion of the closing line before the }. |
|
| 4209 | if (clean_lines.raw_lines[opening_linenum] != |
|
| 4210 | CleanseComments(clean_lines.raw_lines[opening_linenum])): |
|
| 4211 | # Opening line ends with a comment, so conditional isn't empty. |
|
| 4212 | return |
|
| 4213 | if closing_linenum > opening_linenum: |
|
| 4214 | # Opening line after the {. Ignore comments here since we checked above. |
|
| 4215 | bodylist = list(opening_line[opening_pos+1:]) |
|
| 4216 | # All lines until closing line, excluding closing line, with comments. |
|
| 4217 | bodylist.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum]) |
|
| 4218 | # Closing line before the }. Won't (and can't) have comments. |
|
| 4219 | bodylist.append(clean_lines.elided[closing_linenum][:closing_pos-1]) |
|
| 4220 | body = '\n'.join(bodylist) |
|
| 4221 | else: |
|
| 4222 | # If statement has brackets and fits on a single line. |
|
| 4223 | body = opening_line[opening_pos+1:closing_pos-1] |
|
| 4224 | ||
| 4225 | # Check if the body is empty |
|
| 4226 | if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body): |
|
| 4227 | return |
|
| 4228 | # The body is empty. Now make sure there's not an else clause. |
|
| 4229 | current_linenum = closing_linenum |
|
| 4230 | current_line_fragment = closing_line[closing_pos:] |
|
| 4231 | # Loop until EOF or find anything that's not whitespace or else clause. |
|
| 4232 | while Search(r'^\s*$|^(?=\s*else)', current_line_fragment): |
|
| 4233 | if Search(r'^(?=\s*else)', current_line_fragment): |
|
| 4234 | # Found an else clause, so don't log an error. |
|
| 4235 | return |
|
| 4236 | current_linenum += 1 |
|
| 4237 | if current_linenum == len(clean_lines.elided): |
|
| 4238 | break |
|
| 4239 | current_line_fragment = clean_lines.elided[current_linenum] |
|
| 4240 | ||
| 4241 | # The body is empty and there's no else clause until EOF or other code. |
|
| 4242 | error(filename, end_linenum, 'whitespace/empty_if_body', 4, |
|
| 4243 | ('If statement had no body and no else clause')) |
|
| 4244 | ||
| 4245 | ||
| 4246 | def FindCheckMacro(line): |
|