1// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t
2
3@interface NSObject
4+ (instancetype)new;
5+ (instancetype)alloc;
6- (instancetype)init;
7@end
8
9@interface NSProxy  // Root class with no -init method.
10@end
11
12// NSDate provides a specific factory method.
13@interface NSDate : NSObject
14+ (instancetype)date;
15@end
16
17// For testing behavior with Objective-C Generics.
18@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject
19@end
20
21@class NSString;
22
23#define ALLOCATE_OBJECT(_Type) [_Type new]
24
25void CheckSpecificInitRecommendations(void) {
26  NSObject *object = [NSObject new];
27  // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
28  // CHECK-FIXES: [NSObject alloc] init];
29
30  NSDate *correctDate = [NSDate date];
31  NSDate *incorrectDate = [NSDate new];
32  // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
33  // CHECK-FIXES: [NSDate date];
34
35  NSObject *macroCreated = ALLOCATE_OBJECT(NSObject);  // Shouldn't warn on macros.
36
37  NSMutableDictionary *dict = [NSMutableDictionary<NSString *, NSString *> new];
38  // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
39  // CHECK-FIXES: [NSMutableDictionary<NSString *, NSString *> alloc] init];
40}
41
42@interface Foo : NSObject
43+ (instancetype)new; // Declare again to suppress warning.
44- (instancetype)initWithInt:(int)anInt;
45- (instancetype)init __attribute__((unavailable));
46
47- (id)new;
48@end
49
50@interface Baz : Foo // Check unavailable -init through inheritance.
51@end
52
53@interface ProxyFoo : NSProxy
54+ (instancetype)new;
55@end
56
57void CallNewWhenInitUnavailable(void) {
58  Foo *foo = [Foo new];
59  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
60
61  Baz *baz = [Baz new];
62  // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
63
64  // Instance method -new calls may be weird, but are not strictly forbidden.
65  Foo *bar = [[Foo alloc] initWithInt:4];
66  [bar new];
67
68  ProxyFoo *proxy = [ProxyFoo new];
69  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new]
70}
71
72@interface HasNewOverride : NSObject
73@end
74
75@implementation HasNewOverride
76+ (instancetype)new {
77  return [[self alloc] init];
78}
79// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new]
80@end
81