brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.1 KiB · 65d857c Raw
242 lines · plain
1// RUN: %clang_analyze_cc1 -fblocks -analyzer-output=text -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify  %s2 3// The larger set of tests in located in localization.m. These are tests4// specific for non-aggressive reporting.5 6// These declarations were reduced using Delta-Debugging from Foundation.h7// on Mac OS X.8 9#define nil ((id)0)10#define NSLocalizedString(key, comment)                                        \11  [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]12#define NSLocalizedStringFromTable(key, tbl, comment)                          \13  [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]14#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment)          \15  [bundle localizedStringForKey:(key) value:@"" table:(tbl)]16#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment)      \17  [bundle localizedStringForKey:(key) value:(val) table:(tbl)]18@interface NSObject19+ (id)alloc;20- (id)init;21@end22@interface NSString : NSObject23- (NSString *)stringByAppendingFormat:(NSString *)format, ...;24+ (instancetype)stringWithFormat:(NSString *)format, ...;25@end26@interface NSBundle : NSObject27+ (NSBundle *)mainBundle;28- (NSString *)localizedStringForKey:(NSString *)key29                              value:(NSString *)value30                              table:(NSString *)tableName;31@end32@interface UILabel : NSObject33@property(nullable, nonatomic, copy) NSString *text;34@end35@interface TestObject : NSObject36@property(strong) NSString *text;37@end38 39@interface LocalizationTestSuite : NSObject40int random(void);41@property (assign) int unreadArticlesCount;42@end43#define MCLocalizedString(s) NSLocalizedString(s,nil);44// Test cases begin here45@implementation LocalizationTestSuite46 47NSString *KHLocalizedString(NSString* key, NSString* comment) {48    return NSLocalizedString(key, comment);49}50 51// An object passed in as an parameter's string member52// should not be considered unlocalized53- (void)testObjectAsArgument:(TestObject *)argumentObject {54  UILabel *testLabel = [[UILabel alloc] init];55 56  [testLabel setText:[argumentObject text]]; // no-warning57  [testLabel setText:argumentObject.text];   // no-warning58}59 60- (void)testLocalizationErrorDetectedOnPathway {61  UILabel *testLabel = [[UILabel alloc] init];62  NSString *bar = NSLocalizedString(@"Hello", @"Comment");63 64  if (random()) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}65    bar = @"Unlocalized string"; // expected-note {{Non-localized string literal here}}66  }67 68  [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}} expected-note {{User-facing}}69}70 71- (void)testMultipleUnlocalizedStringsInSamePath {72  UILabel *testLabel = [[UILabel alloc] init];73  NSString *bar = @"Unlocalized string"; // no-note74 75  bar = @"Unlocalized string"; // expected-note {{Non-localized string literal here}}76 77  NSString *other = @"Other unlocalized string."; // no-note78  (void)other;79 80  NSString *same = @"Unlocalized string"; // no-note81  (void)same;82 83  [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}} expected-note {{User-facing}}84}85 86- (void)testOneCharacterStringsDoNotGiveAWarning {87  UILabel *testLabel = [[UILabel alloc] init];88  NSString *bar = NSLocalizedString(@"Hello", @"Comment");89 90  if (random()) {91    bar = @"-";92  }93 94  [testLabel setText:bar]; // no-warning95}96 97- (void)testOneCharacterUTFStringsDoNotGiveAWarning {98  UILabel *testLabel = [[UILabel alloc] init];99  NSString *bar = NSLocalizedString(@"Hello", @"Comment");100 101  if (random()) {102    bar = @"\u2014";103  }104 105  [testLabel setText:bar]; // no-warning106}107 108 109// Suppress diagnostic about user-facing string constants when the method name110// contains the term "Debug".111- (void)debugScreen:(UILabel *)label {112  label.text = @"Unlocalized";113}114 115// Plural Misuse Checker Tests116// These tests are modeled off incorrect uses of the many-one pattern117// from real projects. 118 119- (NSString *)test1:(int)plural {120    if (plural) {121        return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}122    }123    return MCLocalizedString(@"TYPE");124}125 126- (NSString *)test2:(int)numOfReminders {127    if (numOfReminders > 0) {128        return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning 2 {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note 2 {{Plural}}129    } 130    return nil;131}132 133- (void)test3 {134    NSString *count;135    if (self.unreadArticlesCount > 1)136    {137        count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}138    } else {139        count = [count stringByAppendingFormat:@"%@",  KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}140    }141}142 143- (NSString *)test4:(int)count {144    if ( count == 1 )145    {146        return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}147    } else {148        return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}149    }150}151 152- (NSString *)test5:(int)count {153	int test = count == 1;154    if (test)155    {156        return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}157    } else {158        return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}159    }160}161 162// This tests the heuristic that the direct parent IfStmt must match the isCheckingPlurality confition to avoid false positives generated from complex code (generally the pattern we're looking for is simple If-Else)163 164- (NSString *)test6:(int)sectionIndex {165	int someOtherVariable = 0;166    if (sectionIndex == 1)167    {168		// Do some other crazy stuff169		if (someOtherVariable)170        	return KHLocalizedString(@"OK",nil); // no-warning171    } else {172        return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported across all languages. Use a .stringsdict file}} expected-note {{Plural}}173    }174	return nil;175}176 177// False positives that we are not accounting for involve matching the heuristic178// of having 1 or 2 in the RHS of a BinaryOperator and having a localized string 179// in the body of the IfStmt. This is seen a lot when checking for the section180// indexpath of something like a UITableView181 182// - (NSString *)testNotAccountedFor:(int)sectionIndex {183//     if (sectionIndex == 1)184//     {185//         return KHLocalizedString(@"1",nil); // false-positive186//     } else if (sectionIndex == 2) {187//     	return KHLocalizedString(@"2",nil); // false-positive188//     } else if (sectionIndex == 3) {189// 		return KHLocalizedString(@"3",nil); // no-false-positive190// 	}191// }192 193// Potential test-cases to support in the future194 195// - (NSString *)test7:(int)count {196//     BOOL plural = count != 1;197//     return KHLocalizedString(plural ? @"PluralString" : @"SingularString", @"");198// }199//200// - (NSString *)test8:(BOOL)plural {201//     return KHLocalizedString(([NSString stringWithFormat:@"RELATIVE_DATE_%@_%@", ((1 == 1) ? @"FUTURE" : @"PAST"), plural ? @"PLURAL" : @"SINGULAR"]));202// }203//204//205//206// - (void)test9:(int)numberOfTimesEarned {207//     NSString* localizedDescriptionKey;208//     if (numberOfTimesEarned == 1) {209//         localizedDescriptionKey = @"SINGULAR_%@";210//     } else {211//         localizedDescriptionKey = @"PLURAL_%@_%@";212//     }213//     NSLocalizedString(localizedDescriptionKey, nil);214// }215//216// - (NSString *)test10 {217//     NSInteger count = self.problems.count;218//     NSString *title = [NSString stringWithFormat:@"%ld Problems", (long) count];219//     if (count < 2) {220//         if (count == 0) {221//             title = [NSString stringWithFormat:@"No Problems Found"];222//         } else {223//             title = [NSString stringWithFormat:@"%ld Problem", (long) count];224//         }225//     }226//     return title;227// }228 229@end230 231 232// Suppress diagnostic about user-facing string constants when the class name233// contains "Debug"234@interface MyDebugView : NSObject235@end236 237@implementation MyDebugView238- (void)setupScreen:(UILabel *)label {239  label.text = @"Unlocalized"; // no-warning240}241@end242