Assignment followed by a glued unary operator, as in =+ or =!
ID |
objectivec.correctness.non_existent_operators |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Suspicious Construct |
Language |
Objective-C |
Description
Reports an = that is preceded by whitespace and immediately followed by +, - or ! with whitespace after it - count =+ 1, total =- 1, flag =! ready. That spacing reads as a single compound operator but is an assignment of a unary expression. The correctly spaced forms = +1, = -1 and = !ready, the real compound operators += and -=, and the comparisons ==, !=, ⇐ and >= are not reported, and neither are occurrences inside a comment or a string literal.
Rationale
count =+ 1 looks like count += 1 but assigns 1, discarding whatever count held; total =- 1 looks like total -= 1 but assigns -1; flag =! ready looks like a != comparison but assigns the negation and, in a condition, is also an assignment where a test was meant. All three compile without a warning in most configurations, and the only clue in the source is the spacing, which is exactly what a reader skims past. Because there is no =+, =- or =! operator, the spacing is the whole signal: it is written that way when someone intended the compound operator and typed it backwards.
The following code illustrates the pattern detected by this rule:
@implementation Counters
- (void)mistyped:(BOOL)ready {
NSInteger count = 0;
// FLAGGED: Assignment followed by a glued unary operator, as in =+ or =!
count =+ 1;
NSInteger total = 10;
// FLAGGED: Assignment followed by a glued unary operator, as in =+ or =!
total =- 1;
BOOL mismatch = NO;
// FLAGGED: Assignment followed by a glued unary operator, as in =+ or =!
mismatch =! ready;
NSLog(@"%ld %ld %d", (long)count, (long)total, mismatch);
}
@end
Remediation
Decide which was meant and write it unambiguously. For accumulation use the compound operator - count += 1, total -= 1. For a comparison use !=. If the assignment of a unary expression really is intended, put the space on the other side - count = +1, flag = !ready - so the operator binds visibly to its operand.