| @@ 3876-3992 (lines=117) @@ | ||
| 3873 | return ('', -1) |
|
| 3874 | ||
| 3875 | ||
| 3876 | def CheckBraces(filename, clean_lines, linenum, error): |
|
| 3877 | """Looks for misplaced braces (e.g. at the end of line). |
|
| 3878 | ||
| 3879 | Args: |
|
| 3880 | filename: The name of the current file. |
|
| 3881 | clean_lines: A CleansedLines instance containing the file. |
|
| 3882 | linenum: The number of the line to check. |
|
| 3883 | error: The function to call with any errors found. |
|
| 3884 | """ |
|
| 3885 | ||
| 3886 | line = clean_lines.elided[linenum] # get rid of comments and strings |
|
| 3887 | ||
| 3888 | if Match(r'\s*{\s*$', line): |
|
| 3889 | # We allow an open brace to start a line in the case where someone is using |
|
| 3890 | # braces in a block to explicitly create a new scope, which is commonly used |
|
| 3891 | # to control the lifetime of stack-allocated variables. Braces are also |
|
| 3892 | # used for brace initializers inside function calls. We don't detect this |
|
| 3893 | # perfectly: we just don't complain if the last non-whitespace character on |
|
| 3894 | # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the |
|
| 3895 | # previous line starts a preprocessor block. We also allow a brace on the |
|
| 3896 | # following line if it is part of an array initialization and would not fit |
|
| 3897 | # within the 80 character limit of the preceding line. |
|
| 3898 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
| 3899 | if (not Search(r'[,;:}{(]\s*$', prevline) and |
|
| 3900 | not Match(r'\s*#', prevline) and |
|
| 3901 | not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)): |
|
| 3902 | error(filename, linenum, 'whitespace/braces', 4, |
|
| 3903 | '{ should almost always be at the end of the previous line') |
|
| 3904 | ||
| 3905 | # An else clause should be on the same line as the preceding closing brace. |
|
| 3906 | if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): |
|
| 3907 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
| 3908 | if Match(r'\s*}\s*$', prevline): |
|
| 3909 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3910 | 'An else should appear on the same line as the preceding }') |
|
| 3911 | ||
| 3912 | # If braces come on one side of an else, they should be on both. |
|
| 3913 | # However, we have to worry about "else if" that spans multiple lines! |
|
| 3914 | if Search(r'else if\s*\(', line): # could be multi-line if |
|
| 3915 | brace_on_left = bool(Search(r'}\s*else if\s*\(', line)) |
|
| 3916 | # find the ( after the if |
|
| 3917 | pos = line.find('else if') |
|
| 3918 | pos = line.find('(', pos) |
|
| 3919 | if pos > 0: |
|
| 3920 | (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) |
|
| 3921 | brace_on_right = endline[endpos:].find('{') != -1 |
|
| 3922 | if brace_on_left != brace_on_right: # must be brace after if |
|
| 3923 | error(filename, linenum, 'readability/braces', 5, |
|
| 3924 | 'If an else has a brace on one side, it should have it on both') |
|
| 3925 | elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): |
|
| 3926 | error(filename, linenum, 'readability/braces', 5, |
|
| 3927 | 'If an else has a brace on one side, it should have it on both') |
|
| 3928 | ||
| 3929 | # Likewise, an else should never have the else clause on the same line |
|
| 3930 | if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): |
|
| 3931 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3932 | 'Else clause should never be on same line as else (use 2 lines)') |
|
| 3933 | ||
| 3934 | # In the same way, a do/while should never be on one line |
|
| 3935 | if Match(r'\s*do [^\s{]', line): |
|
| 3936 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3937 | 'do/while clauses should not be on a single line') |
|
| 3938 | ||
| 3939 | # Check single-line if/else bodies. The style guide says 'curly braces are not |
|
| 3940 | # required for single-line statements'. We additionally allow multi-line, |
|
| 3941 | # single statements, but we reject anything with more than one semicolon in |
|
| 3942 | # it. This means that the first semicolon after the if should be at the end of |
|
| 3943 | # its line, and the line after that should have an indent level equal to or |
|
| 3944 | # lower than the if. We also check for ambiguous if/else nesting without |
|
| 3945 | # braces. |
|
| 3946 | if_else_match = Search(r'\b(if\s*\(|else\b)', line) |
|
| 3947 | if if_else_match and not Match(r'\s*#', line): |
|
| 3948 | if_indent = GetIndentLevel(line) |
|
| 3949 | endline, endlinenum, endpos = line, linenum, if_else_match.end() |
|
| 3950 | if_match = Search(r'\bif\s*\(', line) |
|
| 3951 | if if_match: |
|
| 3952 | # This could be a multiline if condition, so find the end first. |
|
| 3953 | pos = if_match.end() - 1 |
|
| 3954 | (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) |
|
| 3955 | # Check for an opening brace, either directly after the if or on the next |
|
| 3956 | # line. If found, this isn't a single-statement conditional. |
|
| 3957 | if (not Match(r'\s*{', endline[endpos:]) |
|
| 3958 | and not (Match(r'\s*$', endline[endpos:]) |
|
| 3959 | and endlinenum < (len(clean_lines.elided) - 1) |
|
| 3960 | and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))): |
|
| 3961 | while (endlinenum < len(clean_lines.elided) |
|
| 3962 | and ';' not in clean_lines.elided[endlinenum][endpos:]): |
|
| 3963 | endlinenum += 1 |
|
| 3964 | endpos = 0 |
|
| 3965 | if endlinenum < len(clean_lines.elided): |
|
| 3966 | endline = clean_lines.elided[endlinenum] |
|
| 3967 | # We allow a mix of whitespace and closing braces (e.g. for one-liner |
|
| 3968 | # methods) and a single \ after the semicolon (for macros) |
|
| 3969 | endpos = endline.find(';') |
|
| 3970 | if not Match(r';[\s}]*(\\?)$', endline[endpos:]): |
|
| 3971 | # Semicolon isn't the last character, there's something trailing. |
|
| 3972 | # Output a warning if the semicolon is not contained inside |
|
| 3973 | # a lambda expression. |
|
| 3974 | if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$', |
|
| 3975 | endline): |
|
| 3976 | error(filename, linenum, 'readability/braces', 4, |
|
| 3977 | 'If/else bodies with multiple statements require braces') |
|
| 3978 | elif endlinenum < len(clean_lines.elided) - 1: |
|
| 3979 | # Make sure the next line is dedented |
|
| 3980 | next_line = clean_lines.elided[endlinenum + 1] |
|
| 3981 | next_indent = GetIndentLevel(next_line) |
|
| 3982 | # With ambiguous nested if statements, this will error out on the |
|
| 3983 | # if that *doesn't* match the else, regardless of whether it's the |
|
| 3984 | # inner one or outer one. |
|
| 3985 | if (if_match and Match(r'\s*else\b', next_line) |
|
| 3986 | and next_indent != if_indent): |
|
| 3987 | error(filename, linenum, 'readability/braces', 4, |
|
| 3988 | 'Else clause should be indented at the same level as if. ' |
|
| 3989 | 'Ambiguous nested if/else chains require braces.') |
|
| 3990 | elif next_indent > if_indent: |
|
| 3991 | error(filename, linenum, 'readability/braces', 4, |
|
| 3992 | 'If/else bodies with multiple statements require braces') |
|
| 3993 | ||
| 3994 | ||
| 3995 | def CheckTrailingSemicolon(filename, clean_lines, linenum, error): |
|
| @@ 3876-3992 (lines=117) @@ | ||
| 3873 | return ('', -1) |
|
| 3874 | ||
| 3875 | ||
| 3876 | def CheckBraces(filename, clean_lines, linenum, error): |
|
| 3877 | """Looks for misplaced braces (e.g. at the end of line). |
|
| 3878 | ||
| 3879 | Args: |
|
| 3880 | filename: The name of the current file. |
|
| 3881 | clean_lines: A CleansedLines instance containing the file. |
|
| 3882 | linenum: The number of the line to check. |
|
| 3883 | error: The function to call with any errors found. |
|
| 3884 | """ |
|
| 3885 | ||
| 3886 | line = clean_lines.elided[linenum] # get rid of comments and strings |
|
| 3887 | ||
| 3888 | if Match(r'\s*{\s*$', line): |
|
| 3889 | # We allow an open brace to start a line in the case where someone is using |
|
| 3890 | # braces in a block to explicitly create a new scope, which is commonly used |
|
| 3891 | # to control the lifetime of stack-allocated variables. Braces are also |
|
| 3892 | # used for brace initializers inside function calls. We don't detect this |
|
| 3893 | # perfectly: we just don't complain if the last non-whitespace character on |
|
| 3894 | # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the |
|
| 3895 | # previous line starts a preprocessor block. We also allow a brace on the |
|
| 3896 | # following line if it is part of an array initialization and would not fit |
|
| 3897 | # within the 80 character limit of the preceding line. |
|
| 3898 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
| 3899 | if (not Search(r'[,;:}{(]\s*$', prevline) and |
|
| 3900 | not Match(r'\s*#', prevline) and |
|
| 3901 | not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)): |
|
| 3902 | error(filename, linenum, 'whitespace/braces', 4, |
|
| 3903 | '{ should almost always be at the end of the previous line') |
|
| 3904 | ||
| 3905 | # An else clause should be on the same line as the preceding closing brace. |
|
| 3906 | if Match(r'\s*else\b\s*(?:if\b|\{|$)', line): |
|
| 3907 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
| 3908 | if Match(r'\s*}\s*$', prevline): |
|
| 3909 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3910 | 'An else should appear on the same line as the preceding }') |
|
| 3911 | ||
| 3912 | # If braces come on one side of an else, they should be on both. |
|
| 3913 | # However, we have to worry about "else if" that spans multiple lines! |
|
| 3914 | if Search(r'else if\s*\(', line): # could be multi-line if |
|
| 3915 | brace_on_left = bool(Search(r'}\s*else if\s*\(', line)) |
|
| 3916 | # find the ( after the if |
|
| 3917 | pos = line.find('else if') |
|
| 3918 | pos = line.find('(', pos) |
|
| 3919 | if pos > 0: |
|
| 3920 | (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) |
|
| 3921 | brace_on_right = endline[endpos:].find('{') != -1 |
|
| 3922 | if brace_on_left != brace_on_right: # must be brace after if |
|
| 3923 | error(filename, linenum, 'readability/braces', 5, |
|
| 3924 | 'If an else has a brace on one side, it should have it on both') |
|
| 3925 | elif Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): |
|
| 3926 | error(filename, linenum, 'readability/braces', 5, |
|
| 3927 | 'If an else has a brace on one side, it should have it on both') |
|
| 3928 | ||
| 3929 | # Likewise, an else should never have the else clause on the same line |
|
| 3930 | if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): |
|
| 3931 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3932 | 'Else clause should never be on same line as else (use 2 lines)') |
|
| 3933 | ||
| 3934 | # In the same way, a do/while should never be on one line |
|
| 3935 | if Match(r'\s*do [^\s{]', line): |
|
| 3936 | error(filename, linenum, 'whitespace/newline', 4, |
|
| 3937 | 'do/while clauses should not be on a single line') |
|
| 3938 | ||
| 3939 | # Check single-line if/else bodies. The style guide says 'curly braces are not |
|
| 3940 | # required for single-line statements'. We additionally allow multi-line, |
|
| 3941 | # single statements, but we reject anything with more than one semicolon in |
|
| 3942 | # it. This means that the first semicolon after the if should be at the end of |
|
| 3943 | # its line, and the line after that should have an indent level equal to or |
|
| 3944 | # lower than the if. We also check for ambiguous if/else nesting without |
|
| 3945 | # braces. |
|
| 3946 | if_else_match = Search(r'\b(if\s*\(|else\b)', line) |
|
| 3947 | if if_else_match and not Match(r'\s*#', line): |
|
| 3948 | if_indent = GetIndentLevel(line) |
|
| 3949 | endline, endlinenum, endpos = line, linenum, if_else_match.end() |
|
| 3950 | if_match = Search(r'\bif\s*\(', line) |
|
| 3951 | if if_match: |
|
| 3952 | # This could be a multiline if condition, so find the end first. |
|
| 3953 | pos = if_match.end() - 1 |
|
| 3954 | (endline, endlinenum, endpos) = CloseExpression(clean_lines, linenum, pos) |
|
| 3955 | # Check for an opening brace, either directly after the if or on the next |
|
| 3956 | # line. If found, this isn't a single-statement conditional. |
|
| 3957 | if (not Match(r'\s*{', endline[endpos:]) |
|
| 3958 | and not (Match(r'\s*$', endline[endpos:]) |
|
| 3959 | and endlinenum < (len(clean_lines.elided) - 1) |
|
| 3960 | and Match(r'\s*{', clean_lines.elided[endlinenum + 1]))): |
|
| 3961 | while (endlinenum < len(clean_lines.elided) |
|
| 3962 | and ';' not in clean_lines.elided[endlinenum][endpos:]): |
|
| 3963 | endlinenum += 1 |
|
| 3964 | endpos = 0 |
|
| 3965 | if endlinenum < len(clean_lines.elided): |
|
| 3966 | endline = clean_lines.elided[endlinenum] |
|
| 3967 | # We allow a mix of whitespace and closing braces (e.g. for one-liner |
|
| 3968 | # methods) and a single \ after the semicolon (for macros) |
|
| 3969 | endpos = endline.find(';') |
|
| 3970 | if not Match(r';[\s}]*(\\?)$', endline[endpos:]): |
|
| 3971 | # Semicolon isn't the last character, there's something trailing. |
|
| 3972 | # Output a warning if the semicolon is not contained inside |
|
| 3973 | # a lambda expression. |
|
| 3974 | if not Match(r'^[^{};]*\[[^\[\]]*\][^{}]*\{[^{}]*\}\s*\)*[;,]\s*$', |
|
| 3975 | endline): |
|
| 3976 | error(filename, linenum, 'readability/braces', 4, |
|
| 3977 | 'If/else bodies with multiple statements require braces') |
|
| 3978 | elif endlinenum < len(clean_lines.elided) - 1: |
|
| 3979 | # Make sure the next line is dedented |
|
| 3980 | next_line = clean_lines.elided[endlinenum + 1] |
|
| 3981 | next_indent = GetIndentLevel(next_line) |
|
| 3982 | # With ambiguous nested if statements, this will error out on the |
|
| 3983 | # if that *doesn't* match the else, regardless of whether it's the |
|
| 3984 | # inner one or outer one. |
|
| 3985 | if (if_match and Match(r'\s*else\b', next_line) |
|
| 3986 | and next_indent != if_indent): |
|
| 3987 | error(filename, linenum, 'readability/braces', 4, |
|
| 3988 | 'Else clause should be indented at the same level as if. ' |
|
| 3989 | 'Ambiguous nested if/else chains require braces.') |
|
| 3990 | elif next_indent > if_indent: |
|
| 3991 | error(filename, linenum, 'readability/braces', 4, |
|
| 3992 | 'If/else bodies with multiple statements require braces') |
|
| 3993 | ||
| 3994 | ||
| 3995 | def CheckTrailingSemicolon(filename, clean_lines, linenum, error): |
|