Digraph used in place of a bracket, brace or hash
ID |
objectivec.maintainability.avoid_digraphs |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Obscure Syntax |
Language |
Objective-C |
Description
Reports the digraphs <%, %>, <:, :> and %:, which the compiler reads as {, }, [, ] and #. Unlike a trigraph, a digraph is a token spelling rather than a character replacement, so it is not recognised inside a comment or a string literal - occurrences there are text and are not reported. A trigraph is reported by the avoid-trigraphs rule instead.
Rationale
A digraph spells a punctuator with characters that look like something else entirely, so a reader has to translate before they can even see the block structure: if (value > 0) <% opens a brace, and table<:4:> is an array subscript, not a comparison. The two forms of the same punctuator can also be mixed within one file, which defeats brace matching in editors and makes a diff of the affected region unreadable.
The following code illustrates the pattern detected by this rule:
// FLAGGED: Digraph used in place of a bracket, brace or hash
%:define kRetryLimit 3
@implementation Legacy
- (void)arrays {
// FLAGGED: Digraph used in place of a bracket, brace or hash
int table<:4:> = {1, 2, 3, 4};
// FLAGGED: Digraph used in place of a bracket, brace or hash
NSLog(@"first %d", table<:0:>);
}
- (void)braces:(NSInteger)value {
// FLAGGED: Digraph used in place of a bracket, brace or hash
if (value > 0) <% NSLog(@"positive"); %>
}
- (void)plainSyntax:(NSInteger)total count:(NSInteger)count {
NSArray<NSString *> *names = @[@"a", @"b"];
NSDictionary *lookup = @{@"key": @1};
NSInteger rest = total % count;
NSInteger picked = rest > 0 ? total : count;
NSLog(@"%@ %@ %ld", names, lookup, (long)picked);
}
- (void)quoted {
NSString *progress = @"100%> complete";
// the old build wrote <% here %>
/* int legacy<:2:>; */
NSLog(@"%@", progress);
}
@end