@@ 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): |