@@ 3995-4139 (lines=145) @@ | ||
3992 | 'If/else bodies with multiple statements require braces') |
|
3993 | ||
3994 | ||
3995 | def CheckTrailingSemicolon(filename, clean_lines, linenum, error): |
|
3996 | """Looks for redundant trailing semicolon. |
|
3997 | ||
3998 | Args: |
|
3999 | filename: The name of the current file. |
|
4000 | clean_lines: A CleansedLines instance containing the file. |
|
4001 | linenum: The number of the line to check. |
|
4002 | error: The function to call with any errors found. |
|
4003 | """ |
|
4004 | ||
4005 | line = clean_lines.elided[linenum] |
|
4006 | ||
4007 | # Block bodies should not be followed by a semicolon. Due to C++11 |
|
4008 | # brace initialization, there are more places where semicolons are |
|
4009 | # required than not, so we use a whitelist approach to check these |
|
4010 | # rather than a blacklist. These are the places where "};" should |
|
4011 | # be replaced by just "}": |
|
4012 | # 1. Some flavor of block following closing parenthesis: |
|
4013 | # for (;;) {}; |
|
4014 | # while (...) {}; |
|
4015 | # switch (...) {}; |
|
4016 | # Function(...) {}; |
|
4017 | # if (...) {}; |
|
4018 | # if (...) else if (...) {}; |
|
4019 | # |
|
4020 | # 2. else block: |
|
4021 | # if (...) else {}; |
|
4022 | # |
|
4023 | # 3. const member function: |
|
4024 | # Function(...) const {}; |
|
4025 | # |
|
4026 | # 4. Block following some statement: |
|
4027 | # x = 42; |
|
4028 | # {}; |
|
4029 | # |
|
4030 | # 5. Block at the beginning of a function: |
|
4031 | # Function(...) { |
|
4032 | # {}; |
|
4033 | # } |
|
4034 | # |
|
4035 | # Note that naively checking for the preceding "{" will also match |
|
4036 | # braces inside multi-dimensional arrays, but this is fine since |
|
4037 | # that expression will not contain semicolons. |
|
4038 | # |
|
4039 | # 6. Block following another block: |
|
4040 | # while (true) {} |
|
4041 | # {}; |
|
4042 | # |
|
4043 | # 7. End of namespaces: |
|
4044 | # namespace {}; |
|
4045 | # |
|
4046 | # These semicolons seems far more common than other kinds of |
|
4047 | # redundant semicolons, possibly due to people converting classes |
|
4048 | # to namespaces. For now we do not warn for this case. |
|
4049 | # |
|
4050 | # Try matching case 1 first. |
|
4051 | match = Match(r'^(.*\)\s*)\{', line) |
|
4052 | if match: |
|
4053 | # Matched closing parenthesis (case 1). Check the token before the |
|
4054 | # matching opening parenthesis, and don't warn if it looks like a |
|
4055 | # macro. This avoids these false positives: |
|
4056 | # - macro that defines a base class |
|
4057 | # - multi-line macro that defines a base class |
|
4058 | # - macro that defines the whole class-head |
|
4059 | # |
|
4060 | # But we still issue warnings for macros that we know are safe to |
|
4061 | # warn, specifically: |
|
4062 | # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P |
|
4063 | # - TYPED_TEST |
|
4064 | # - INTERFACE_DEF |
|
4065 | # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: |
|
4066 | # |
|
4067 | # We implement a whitelist of safe macros instead of a blacklist of |
|
4068 | # unsafe macros, even though the latter appears less frequently in |
|
4069 | # google code and would have been easier to implement. This is because |
|
4070 | # the downside for getting the whitelist wrong means some extra |
|
4071 | # semicolons, while the downside for getting the blacklist wrong |
|
4072 | # would result in compile errors. |
|
4073 | # |
|
4074 | # In addition to macros, we also don't want to warn on |
|
4075 | # - Compound literals |
|
4076 | # - Lambdas |
|
4077 | # - alignas specifier with anonymous structs |
|
4078 | # - decltype |
|
4079 | closing_brace_pos = match.group(1).rfind(')') |
|
4080 | opening_parenthesis = ReverseCloseExpression( |
|
4081 | clean_lines, linenum, closing_brace_pos) |
|
4082 | if opening_parenthesis[2] > -1: |
|
4083 | line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] |
|
4084 | macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix) |
|
4085 | func = Match(r'^(.*\])\s*$', line_prefix) |
|
4086 | if ((macro and |
|
4087 | macro.group(1) not in ( |
|
4088 | 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', |
|
4089 | 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', |
|
4090 | 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or |
|
4091 | (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or |
|
4092 | Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or |
|
4093 | Search(r'\bdecltype$', line_prefix) or |
|
4094 | Search(r'\s+=\s*$', line_prefix)): |
|
4095 | match = None |
|
4096 | if (match and |
|
4097 | opening_parenthesis[1] > 1 and |
|
4098 | Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): |
|
4099 | # Multi-line lambda-expression |
|
4100 | match = None |
|
4101 | ||
4102 | else: |
|
4103 | # Try matching cases 2-3. |
|
4104 | match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) |
|
4105 | if not match: |
|
4106 | # Try matching cases 4-6. These are always matched on separate lines. |
|
4107 | # |
|
4108 | # Note that we can't simply concatenate the previous line to the |
|
4109 | # current line and do a single match, otherwise we may output |
|
4110 | # duplicate warnings for the blank line case: |
|
4111 | # if (cond) { |
|
4112 | # // blank line |
|
4113 | # } |
|
4114 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
4115 | if prevline and Search(r'[;{}]\s*$', prevline): |
|
4116 | match = Match(r'^(\s*)\{', line) |
|
4117 | ||
4118 | # Check matching closing brace |
|
4119 | if match: |
|
4120 | (endline, endlinenum, endpos) = CloseExpression( |
|
4121 | clean_lines, linenum, len(match.group(1))) |
|
4122 | if endpos > -1 and Match(r'^\s*;', endline[endpos:]): |
|
4123 | # Current {} pair is eligible for semicolon check, and we have found |
|
4124 | # the redundant semicolon, output warning here. |
|
4125 | # |
|
4126 | # Note: because we are scanning forward for opening braces, and |
|
4127 | # outputting warnings for the matching closing brace, if there are |
|
4128 | # nested blocks with trailing semicolons, we will get the error |
|
4129 | # messages in reversed order. |
|
4130 | ||
4131 | # We need to check the line forward for NOLINT |
|
4132 | raw_lines = clean_lines.raw_lines |
|
4133 | ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1, |
|
4134 | error) |
|
4135 | ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum, |
|
4136 | error) |
|
4137 | ||
4138 | error(filename, endlinenum, 'readability/braces', 4, |
|
4139 | "You don't need a ; after a }") |
|
4140 | ||
4141 | ||
4142 | def CheckEmptyBlockBody(filename, clean_lines, linenum, error): |
@@ 3995-4139 (lines=145) @@ | ||
3992 | 'If/else bodies with multiple statements require braces') |
|
3993 | ||
3994 | ||
3995 | def CheckTrailingSemicolon(filename, clean_lines, linenum, error): |
|
3996 | """Looks for redundant trailing semicolon. |
|
3997 | ||
3998 | Args: |
|
3999 | filename: The name of the current file. |
|
4000 | clean_lines: A CleansedLines instance containing the file. |
|
4001 | linenum: The number of the line to check. |
|
4002 | error: The function to call with any errors found. |
|
4003 | """ |
|
4004 | ||
4005 | line = clean_lines.elided[linenum] |
|
4006 | ||
4007 | # Block bodies should not be followed by a semicolon. Due to C++11 |
|
4008 | # brace initialization, there are more places where semicolons are |
|
4009 | # required than not, so we use a whitelist approach to check these |
|
4010 | # rather than a blacklist. These are the places where "};" should |
|
4011 | # be replaced by just "}": |
|
4012 | # 1. Some flavor of block following closing parenthesis: |
|
4013 | # for (;;) {}; |
|
4014 | # while (...) {}; |
|
4015 | # switch (...) {}; |
|
4016 | # Function(...) {}; |
|
4017 | # if (...) {}; |
|
4018 | # if (...) else if (...) {}; |
|
4019 | # |
|
4020 | # 2. else block: |
|
4021 | # if (...) else {}; |
|
4022 | # |
|
4023 | # 3. const member function: |
|
4024 | # Function(...) const {}; |
|
4025 | # |
|
4026 | # 4. Block following some statement: |
|
4027 | # x = 42; |
|
4028 | # {}; |
|
4029 | # |
|
4030 | # 5. Block at the beginning of a function: |
|
4031 | # Function(...) { |
|
4032 | # {}; |
|
4033 | # } |
|
4034 | # |
|
4035 | # Note that naively checking for the preceding "{" will also match |
|
4036 | # braces inside multi-dimensional arrays, but this is fine since |
|
4037 | # that expression will not contain semicolons. |
|
4038 | # |
|
4039 | # 6. Block following another block: |
|
4040 | # while (true) {} |
|
4041 | # {}; |
|
4042 | # |
|
4043 | # 7. End of namespaces: |
|
4044 | # namespace {}; |
|
4045 | # |
|
4046 | # These semicolons seems far more common than other kinds of |
|
4047 | # redundant semicolons, possibly due to people converting classes |
|
4048 | # to namespaces. For now we do not warn for this case. |
|
4049 | # |
|
4050 | # Try matching case 1 first. |
|
4051 | match = Match(r'^(.*\)\s*)\{', line) |
|
4052 | if match: |
|
4053 | # Matched closing parenthesis (case 1). Check the token before the |
|
4054 | # matching opening parenthesis, and don't warn if it looks like a |
|
4055 | # macro. This avoids these false positives: |
|
4056 | # - macro that defines a base class |
|
4057 | # - multi-line macro that defines a base class |
|
4058 | # - macro that defines the whole class-head |
|
4059 | # |
|
4060 | # But we still issue warnings for macros that we know are safe to |
|
4061 | # warn, specifically: |
|
4062 | # - TEST, TEST_F, TEST_P, MATCHER, MATCHER_P |
|
4063 | # - TYPED_TEST |
|
4064 | # - INTERFACE_DEF |
|
4065 | # - EXCLUSIVE_LOCKS_REQUIRED, SHARED_LOCKS_REQUIRED, LOCKS_EXCLUDED: |
|
4066 | # |
|
4067 | # We implement a whitelist of safe macros instead of a blacklist of |
|
4068 | # unsafe macros, even though the latter appears less frequently in |
|
4069 | # google code and would have been easier to implement. This is because |
|
4070 | # the downside for getting the whitelist wrong means some extra |
|
4071 | # semicolons, while the downside for getting the blacklist wrong |
|
4072 | # would result in compile errors. |
|
4073 | # |
|
4074 | # In addition to macros, we also don't want to warn on |
|
4075 | # - Compound literals |
|
4076 | # - Lambdas |
|
4077 | # - alignas specifier with anonymous structs |
|
4078 | # - decltype |
|
4079 | closing_brace_pos = match.group(1).rfind(')') |
|
4080 | opening_parenthesis = ReverseCloseExpression( |
|
4081 | clean_lines, linenum, closing_brace_pos) |
|
4082 | if opening_parenthesis[2] > -1: |
|
4083 | line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]] |
|
4084 | macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix) |
|
4085 | func = Match(r'^(.*\])\s*$', line_prefix) |
|
4086 | if ((macro and |
|
4087 | macro.group(1) not in ( |
|
4088 | 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST', |
|
4089 | 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED', |
|
4090 | 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or |
|
4091 | (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or |
|
4092 | Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or |
|
4093 | Search(r'\bdecltype$', line_prefix) or |
|
4094 | Search(r'\s+=\s*$', line_prefix)): |
|
4095 | match = None |
|
4096 | if (match and |
|
4097 | opening_parenthesis[1] > 1 and |
|
4098 | Search(r'\]\s*$', clean_lines.elided[opening_parenthesis[1] - 1])): |
|
4099 | # Multi-line lambda-expression |
|
4100 | match = None |
|
4101 | ||
4102 | else: |
|
4103 | # Try matching cases 2-3. |
|
4104 | match = Match(r'^(.*(?:else|\)\s*const)\s*)\{', line) |
|
4105 | if not match: |
|
4106 | # Try matching cases 4-6. These are always matched on separate lines. |
|
4107 | # |
|
4108 | # Note that we can't simply concatenate the previous line to the |
|
4109 | # current line and do a single match, otherwise we may output |
|
4110 | # duplicate warnings for the blank line case: |
|
4111 | # if (cond) { |
|
4112 | # // blank line |
|
4113 | # } |
|
4114 | prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] |
|
4115 | if prevline and Search(r'[;{}]\s*$', prevline): |
|
4116 | match = Match(r'^(\s*)\{', line) |
|
4117 | ||
4118 | # Check matching closing brace |
|
4119 | if match: |
|
4120 | (endline, endlinenum, endpos) = CloseExpression( |
|
4121 | clean_lines, linenum, len(match.group(1))) |
|
4122 | if endpos > -1 and Match(r'^\s*;', endline[endpos:]): |
|
4123 | # Current {} pair is eligible for semicolon check, and we have found |
|
4124 | # the redundant semicolon, output warning here. |
|
4125 | # |
|
4126 | # Note: because we are scanning forward for opening braces, and |
|
4127 | # outputting warnings for the matching closing brace, if there are |
|
4128 | # nested blocks with trailing semicolons, we will get the error |
|
4129 | # messages in reversed order. |
|
4130 | ||
4131 | # We need to check the line forward for NOLINT |
|
4132 | raw_lines = clean_lines.raw_lines |
|
4133 | ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1, |
|
4134 | error) |
|
4135 | ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum, |
|
4136 | error) |
|
4137 | ||
4138 | error(filename, endlinenum, 'readability/braces', 4, |
|
4139 | "You don't need a ; after a }") |
|
4140 | ||
4141 | ||
4142 | def CheckEmptyBlockBody(filename, clean_lines, linenum, error): |