]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/localization.m
Vendor import of clang trunk r256633:
[FreeBSD/FreeBSD.git] / test / Analysis / localization.m
1 // RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=alpha.osx.cocoa.localizability.PluralMisuseChecker -verify  %s
2
3 // The larger set of tests in located in localization.m. These are tests
4 // specific for non-aggressive reporting.
5
6 // These declarations were reduced using Delta-Debugging from Foundation.h
7 // 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 NSObject
19 + (id)alloc;
20 - (id)init;
21 @end
22 @interface NSString : NSObject
23 - (NSString *)stringByAppendingFormat:(NSString *)format, ...;
24 + (instancetype)stringWithFormat:(NSString *)format, ...;
25 @end
26 @interface NSBundle : NSObject
27 + (NSBundle *)mainBundle;
28 - (NSString *)localizedStringForKey:(NSString *)key
29                               value:(NSString *)value
30                               table:(NSString *)tableName;
31 @end
32 @interface UILabel : NSObject
33 @property(nullable, nonatomic, copy) NSString *text;
34 @end
35 @interface TestObject : NSObject
36 @property(strong) NSString *text;
37 @end
38
39 @interface LocalizationTestSuite : NSObject
40 int random();
41 @property (assign) int unreadArticlesCount;
42 @end
43 #define MCLocalizedString(s) NSLocalizedString(s,nil);
44 // Test cases begin here
45 @implementation LocalizationTestSuite
46
47 NSString *KHLocalizedString(NSString* key, NSString* comment) {
48     return NSLocalizedString(key, comment);
49 }
50
51 // An object passed in as an parameter's string member
52 // should not be considered unlocalized
53 - (void)testObjectAsArgument:(TestObject *)argumentObject {
54   UILabel *testLabel = [[UILabel alloc] init];
55
56   [testLabel setText:[argumentObject text]]; // no-warning
57   [testLabel setText:argumentObject.text];   // no-warning
58 }
59
60 - (void)testLocalizationErrorDetectedOnPathway {
61   UILabel *testLabel = [[UILabel alloc] init];
62   NSString *bar = NSLocalizedString(@"Hello", @"Comment");
63
64   if (random()) {
65     bar = @"Unlocalized string";
66   }
67
68   [testLabel setText:bar]; // expected-warning {{User-facing text should use localized string macro}}
69 }
70
71 - (void)testOneCharacterStringsDoNotGiveAWarning {
72   UILabel *testLabel = [[UILabel alloc] init];
73   NSString *bar = NSLocalizedString(@"Hello", @"Comment");
74
75   if (random()) {
76     bar = @"-";
77   }
78
79   [testLabel setText:bar]; // no-warning
80 }
81
82 - (void)testOneCharacterUTFStringsDoNotGiveAWarning {
83   UILabel *testLabel = [[UILabel alloc] init];
84   NSString *bar = NSLocalizedString(@"Hello", @"Comment");
85
86   if (random()) {
87     bar = @"\u2014";
88   }
89
90   [testLabel setText:bar]; // no-warning
91 }
92
93 // Plural Misuse Checker Tests
94 // These tests are modeled off incorrect uses of the many-one pattern
95 // from real projects. 
96
97 - (NSString *)test1:(int)plural {
98     if (plural) {
99         return MCLocalizedString(@"TYPE_PLURAL"); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
100     }
101     return MCLocalizedString(@"TYPE");
102 }
103
104 - (NSString *)test2:(int)numOfReminders {
105     if (numOfReminders > 0) {
106         return [NSString stringWithFormat:@"%@, %@", @"Test", (numOfReminders != 1) ? [NSString stringWithFormat:NSLocalizedString(@"%@ Reminders", @"Plural count of reminders"), numOfReminders] : [NSString stringWithFormat:NSLocalizedString(@"1 reminder", @"One reminder")]]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}} expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
107     } 
108     return nil;
109 }
110
111 - (void)test3 {
112     NSString *count;
113     if (self.unreadArticlesCount > 1)
114     {
115         count = [count stringByAppendingFormat:@"%@", KHLocalizedString(@"New Stories", @"Plural count for new stories")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
116     } else {
117         count = [count stringByAppendingFormat:@"%@",  KHLocalizedString(@"New Story", @"One new story")]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
118     }
119 }
120
121 - (NSString *)test4:(int)count {
122     if ( count == 1 )
123     {
124         return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
125     } else {
126         return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
127     }
128 }
129
130 - (NSString *)test5:(int)count {
131         int test = count == 1;
132     if (test)
133     {
134         return [NSString stringWithFormat:KHLocalizedString(@"value.singular",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
135     } else {
136         return [NSString stringWithFormat:KHLocalizedString(@"value.plural",nil), count]; // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
137     }
138 }
139
140 // 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)
141
142 - (NSString *)test6:(int)sectionIndex {
143         int someOtherVariable = 0;
144     if (sectionIndex == 1)
145     {
146                 // Do some other crazy stuff
147                 if (someOtherVariable)
148                 return KHLocalizedString(@"OK",nil); // no-warning
149     } else {
150         return KHLocalizedString(@"value.plural",nil); // expected-warning {{Plural cases are not supported accross all languages. Use a .stringsdict file}}
151     }
152         return nil;
153 }
154
155 // False positives that we are not accounting for involve matching the heuristic
156 // of having 1 or 2 in the RHS of a BinaryOperator and having a localized string 
157 // in the body of the IfStmt. This is seen a lot when checking for the section
158 // indexpath of something like a UITableView
159
160 // - (NSString *)testNotAccountedFor:(int)sectionIndex {
161 //     if (sectionIndex == 1)
162 //     {
163 //         return KHLocalizedString(@"1",nil); // false-positive
164 //     } else if (sectionIndex == 2) {
165 //      return KHLocalizedString(@"2",nil); // false-positive
166 //     } else if (sectionIndex == 3) {
167 //              return KHLocalizedString(@"3",nil); // no-false-positive
168 //      }
169 // }
170
171 // Potential test-cases to support in the future
172
173 // - (NSString *)test7:(int)count {
174 //     BOOL plural = count != 1;
175 //     return KHLocalizedString(plural ? @"PluralString" : @"SingularString", @"");
176 // }
177 //
178 // - (NSString *)test8:(BOOL)plural {
179 //     return KHLocalizedString(([NSString stringWithFormat:@"RELATIVE_DATE_%@_%@", ((1 == 1) ? @"FUTURE" : @"PAST"), plural ? @"PLURAL" : @"SINGULAR"]));
180 // }
181 //
182 //
183 //
184 // - (void)test9:(int)numberOfTimesEarned {
185 //     NSString* localizedDescriptionKey;
186 //     if (numberOfTimesEarned == 1) {
187 //         localizedDescriptionKey = @"SINGULAR_%@";
188 //     } else {
189 //         localizedDescriptionKey = @"PLURAL_%@_%@";
190 //     }
191 //     NSLocalizedString(localizedDescriptionKey, nil);
192 // }
193 //
194 // - (NSString *)test10 {
195 //     NSInteger count = self.problems.count;
196 //     NSString *title = [NSString stringWithFormat:@"%ld Problems", (long) count];
197 //     if (count < 2) {
198 //         if (count == 0) {
199 //             title = [NSString stringWithFormat:@"No Problems Found"];
200 //         } else {
201 //             title = [NSString stringWithFormat:@"%ld Problem", (long) count];
202 //         }
203 //     }
204 //     return title;
205 // }
206
207 @end