Skip to content

Commit

Permalink
RCTUtils Obj-C nullability annotations
Browse files Browse the repository at this point in the history
Summary:
Add Objective-C nullability annotations to RCTUtils

public

Reviewed By: javache

Differential Revision: D2797331

fb-gh-sync-id: b918179625865760edc8c6fcc189ad78f819f3e3
  • Loading branch information
nicklockwood authored and facebook-github-bot-7 committed Jan 21, 2016
1 parent d33b554 commit 34d5fa2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 55 deletions.
6 changes: 3 additions & 3 deletions React/Base/RCTAssert.m
Expand Up @@ -119,7 +119,7 @@ void _RCTAssertFormat(


void RCTFatal(NSError *error) void RCTFatal(NSError *error)
{ {
_RCTLogNativeInternal(RCTLogLevelFatal, NULL, 0, @"%@", [error localizedDescription]); _RCTLogNativeInternal(RCTLogLevelFatal, NULL, 0, @"%@", error.localizedDescription);


RCTFatalHandler fatalHandler = RCTGetFatalHandler(); RCTFatalHandler fatalHandler = RCTGetFatalHandler();
if (fatalHandler) { if (fatalHandler) {
Expand All @@ -128,8 +128,8 @@ void RCTFatal(NSError *error)
#if DEBUG #if DEBUG
@try { @try {
#endif #endif
NSString *name = [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, [error localizedDescription]]; NSString *name = [NSString stringWithFormat:@"%@: %@", RCTFatalExceptionName, error.localizedDescription];
NSString *message = RCTFormatError([error localizedDescription], error.userInfo[RCTJSStackTraceKey], 75); NSString *message = RCTFormatError(error.localizedDescription, error.userInfo[RCTJSStackTraceKey], 75);
[NSException raise:name format:@"%@", message]; [NSException raise:name format:@"%@", message];
#if DEBUG #if DEBUG
} @catch (NSException *e) {} } @catch (NSException *e) {}
Expand Down
48 changes: 26 additions & 22 deletions React/Base/RCTUtils.h
Expand Up @@ -16,10 +16,12 @@
#import "RCTAssert.h" #import "RCTAssert.h"
#import "RCTDefines.h" #import "RCTDefines.h"


NS_ASSUME_NONNULL_BEGIN

// JSON serialization/deserialization // JSON serialization/deserialization
RCT_EXTERN NSString *RCTJSONStringify(id jsonObject, NSError **error); RCT_EXTERN NSString *__nullable RCTJSONStringify(id __nullable jsonObject, NSError **error);
RCT_EXTERN id RCTJSONParse(NSString *jsonString, NSError **error); RCT_EXTERN id __nullable RCTJSONParse(NSString *__nullable jsonString, NSError **error);
RCT_EXTERN id RCTJSONParseMutable(NSString *jsonString, NSError **error); RCT_EXTERN id __nullable RCTJSONParseMutable(NSString *__nullable jsonString, NSError **error);


// Strip non JSON-safe values from an object graph // Strip non JSON-safe values from an object graph
RCT_EXTERN id RCTJSONClean(id object); RCT_EXTERN id RCTJSONClean(id object);
Expand Down Expand Up @@ -51,13 +53,13 @@ RCT_EXTERN void RCTSwapInstanceMethods(Class cls, SEL original, SEL replacement)
RCT_EXTERN BOOL RCTClassOverridesClassMethod(Class cls, SEL selector); RCT_EXTERN BOOL RCTClassOverridesClassMethod(Class cls, SEL selector);
RCT_EXTERN BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector); RCT_EXTERN BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector);


// Creates a standardized error object // Creates a standardized error object to return in callbacks
RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData); RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeError(NSString *message, id __nullable toStringify, NSDictionary<NSString *, id> *__nullable extraData);
RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData); RCT_EXTERN NSDictionary<NSString *, id> *RCTMakeAndLogError(NSString *message, id __nullable toStringify, NSDictionary<NSString *, id> *__nullable extraData);
RCT_EXTERN NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error); RCT_EXTERN NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error);
RCT_EXTERN NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *error); RCT_EXTERN NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *__nullable error);


// The default error code that will be sent in the .code value of the Error object to js // The default error code to use as the `code` property for callback error objects
RCT_EXTERN NSString *const RCTErrorUnspecified; RCT_EXTERN NSString *const RCTErrorUnspecified;


// Returns YES if React is running in a test environment // Returns YES if React is running in a test environment
Expand All @@ -67,26 +69,26 @@ RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
RCT_EXTERN BOOL RCTRunningInAppExtension(void); RCT_EXTERN BOOL RCTRunningInAppExtension(void);


// Returns the shared UIApplication instance, or nil if running in an App Extension // Returns the shared UIApplication instance, or nil if running in an App Extension
RCT_EXTERN UIApplication *RCTSharedApplication(void); RCT_EXTERN UIApplication *__nullable RCTSharedApplication(void);


// Returns the current main window, useful if you need to access the root view // Returns the current main window, useful if you need to access the root view
// or view controller, e.g. to present a modal view controller or alert. // or view controller, e.g. to present a modal view controller or alert.
RCT_EXTERN UIWindow *RCTKeyWindow(void); RCT_EXTERN UIWindow *__nullable RCTKeyWindow(void);


// Return a UIAlertView initialized with the given values // Return a UIAlertView initialized with the given values
// or nil if running in an app extension // or nil if running in an app extension
RCT_EXTERN UIAlertView *RCTAlertView(NSString *title, RCT_EXTERN UIAlertView *__nullable RCTAlertView(NSString *title,
NSString *message, NSString *__nullable message,
id delegate, id __nullable delegate,
NSString *cancelButtonTitle, NSString *__nullable cancelButtonTitle,
NSArray<NSString *> *otherButtonTitles); NSArray<NSString *> *__nullable otherButtonTitles);


// Create an NSError in the RCTErrorDomain // Create an NSError in the RCTErrorDomain
RCT_EXTERN NSError *RCTErrorWithMessage(NSString *message); RCT_EXTERN NSError *RCTErrorWithMessage(NSString *message);


// Convert nil values to NSNull, and vice-versa // Convert nil values to NSNull, and vice-versa
RCT_EXTERN id RCTNilIfNull(id value); RCT_EXTERN id __nullable RCTNilIfNull(id __nullable value);
RCT_EXTERN id RCTNullIfNil(id value); RCT_EXTERN id RCTNullIfNil(id __nullable value);


// Convert NaN or infinite values to zero, as these aren't JSON-safe // Convert NaN or infinite values to zero, as these aren't JSON-safe
RCT_EXTERN double RCTZeroIfNaN(double value); RCT_EXTERN double RCTZeroIfNaN(double value);
Expand All @@ -95,14 +97,14 @@ RCT_EXTERN double RCTZeroIfNaN(double value);
RCT_EXTERN NSURL *RCTDataURL(NSString *mimeType, NSData *data); RCT_EXTERN NSURL *RCTDataURL(NSString *mimeType, NSData *data);


// Gzip functionality - compression level in range 0 - 1 (-1 for default) // Gzip functionality - compression level in range 0 - 1 (-1 for default)
RCT_EXTERN NSData *RCTGzipData(NSData *data, float level); RCT_EXTERN NSData *RCTGzipData(NSData *__nullable data, float level);


// Returns the relative path within the main bundle for an absolute URL // Returns the relative path within the main bundle for an absolute URL
// (or nil, if the URL does not specify a path within the main bundle) // (or nil, if the URL does not specify a path within the main bundle)
RCT_EXTERN NSString *RCTBundlePathForURL(NSURL *URL); RCT_EXTERN NSString *__nullable RCTBundlePathForURL(NSURL *__nullable URL);


// Determines if a given image URL actually refers to an XCAsset // Determines if a given image URL actually refers to an XCAsset
RCT_EXTERN BOOL RCTIsXCAssetURL(NSURL *imageURL); RCT_EXTERN BOOL RCTIsXCAssetURL(NSURL *__nullable imageURL);


// Converts a CGColor to a hex string // Converts a CGColor to a hex string
RCT_EXTERN NSString *RCTColorToHexString(CGColorRef color); RCT_EXTERN NSString *RCTColorToHexString(CGColorRef color);
Expand All @@ -111,5 +113,7 @@ RCT_EXTERN NSString *RCTColorToHexString(CGColorRef color);
RCT_EXTERN NSString *RCTUIKitLocalizedString(NSString *string); RCT_EXTERN NSString *RCTUIKitLocalizedString(NSString *string);


// URL manipulation // URL manipulation
RCT_EXTERN NSString *RCTGetURLQueryParam(NSURL *URL, NSString *param); RCT_EXTERN NSString *__nullable RCTGetURLQueryParam(NSURL *__nullable URL, NSString *param);
RCT_EXTERN NSURL *RCTURLByReplacingQueryParam(NSURL *URL, NSString *param, NSString *value); RCT_EXTERN NSURL *__nullable RCTURLByReplacingQueryParam(NSURL *__nullable URL, NSString *param, NSString *__nullable value);

NS_ASSUME_NONNULL_END
67 changes: 37 additions & 30 deletions React/Base/RCTUtils.m
Expand Up @@ -23,7 +23,7 @@


NSString *const RCTErrorUnspecified = @"EUNSPECIFIED"; NSString *const RCTErrorUnspecified = @"EUNSPECIFIED";


NSString *RCTJSONStringify(id jsonObject, NSError **error) NSString *__nullable RCTJSONStringify(id __nullable jsonObject, NSError **error)
{ {
static SEL JSONKitSelector = NULL; static SEL JSONKitSelector = NULL;
static NSSet<Class> *collectionTypes; static NSSet<Class> *collectionTypes;
Expand All @@ -44,14 +44,14 @@
} }


// Use Foundation JSON method // Use Foundation JSON method
NSData *jsonData = [NSJSONSerialization NSData *jsonData = jsonObject ? [NSJSONSerialization
dataWithJSONObject:jsonObject dataWithJSONObject:jsonObject
options:(NSJSONWritingOptions)NSJSONReadingAllowFragments options:(NSJSONWritingOptions)NSJSONReadingAllowFragments
error:error]; error:error] : nil;
return jsonData ? [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] : nil; return jsonData ? [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] : nil;
} }


static id _RCTJSONParse(NSString *jsonString, BOOL mutable, NSError **error) static id __nullable _RCTJSONParse(NSString *__nullable jsonString, BOOL mutable, NSError **error)
{ {
static SEL JSONKitSelector = NULL; static SEL JSONKitSelector = NULL;
static SEL JSONKitMutableSelector = NULL; static SEL JSONKitMutableSelector = NULL;
Expand Down Expand Up @@ -110,12 +110,12 @@ static id _RCTJSONParse(NSString *jsonString, BOOL mutable, NSError **error)
return nil; return nil;
} }


id RCTJSONParse(NSString *jsonString, NSError **error) id __nullable RCTJSONParse(NSString *__nullable jsonString, NSError **error)
{ {
return _RCTJSONParse(jsonString, NO, error); return _RCTJSONParse(jsonString, NO, error);
} }


id RCTJSONParseMutable(NSString *jsonString, NSError **error) id __nullable RCTJSONParseMutable(NSString *__nullable jsonString, NSError **error)
{ {
return _RCTJSONParse(jsonString, YES, error); return _RCTJSONParse(jsonString, YES, error);
} }
Expand Down Expand Up @@ -311,18 +311,22 @@ BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)
return NO; return NO;
} }


NSDictionary<NSString *, id> *RCTMakeError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData) NSDictionary<NSString *, id> *RCTMakeError(NSString *message,
id __nullable toStringify,
NSDictionary<NSString *, id> *__nullable extraData)
{ {
if (toStringify) { if (toStringify) {
message = [message stringByAppendingString:[toStringify description]]; message = [message stringByAppendingString:[toStringify description]];
} }


NSMutableDictionary<NSString *, id> *error = [NSMutableDictionary dictionaryWithDictionary:extraData]; NSMutableDictionary<NSString *, id> *error = [extraData mutableCopy] ?: [NSMutableDictionary new];
error[@"message"] = message; error[@"message"] = message;
return error; return error;
} }


NSDictionary<NSString *, id> *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary<NSString *, id> *extraData) NSDictionary<NSString *, id> *RCTMakeAndLogError(NSString *message,
id __nullable toStringify,
NSDictionary<NSString *, id> *__nullable extraData)
{ {
NSDictionary<NSString *, id> *error = RCTMakeError(message, toStringify, extraData); NSDictionary<NSString *, id> *error = RCTMakeError(message, toStringify, extraData);
RCTLogError(@"\nError: %@", error); RCTLogError(@"\nError: %@", error);
Expand All @@ -331,11 +335,15 @@ BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)


NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error) NSDictionary<NSString *, id> *RCTJSErrorFromNSError(NSError *error)
{ {
return RCTJSErrorFromCodeMessageAndNSError(RCTErrorUnspecified, nil, error); return RCTJSErrorFromCodeMessageAndNSError(RCTErrorUnspecified,
error.localizedDescription,
error);
} }


// TODO: Can we just replace RCTMakeError with this function instead? // TODO: Can we just replace RCTMakeError with this function instead?
NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code, NSString *message, NSError *error) NSDictionary<NSString *, id> *RCTJSErrorFromCodeMessageAndNSError(NSString *code,
NSString *message,
NSError *__nullable error)
{ {
NSString *errorMessage; NSString *errorMessage;
NSArray<NSString *> *stackTrace = [NSThread callStackSymbols]; NSArray<NSString *> *stackTrace = [NSThread callStackSymbols];
Expand All @@ -356,7 +364,6 @@ BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)
return RCTMakeError(errorMessage, nil, errorInfo); return RCTMakeError(errorMessage, nil, errorInfo);
} }



BOOL RCTRunningInTestEnvironment(void) BOOL RCTRunningInTestEnvironment(void)
{ {
static BOOL isTestEnvironment = NO; static BOOL isTestEnvironment = NO;
Expand All @@ -372,15 +379,15 @@ BOOL RCTRunningInAppExtension(void)
return [[[[NSBundle mainBundle] bundlePath] pathExtension] isEqualToString:@"appex"]; return [[[[NSBundle mainBundle] bundlePath] pathExtension] isEqualToString:@"appex"];
} }


UIApplication *RCTSharedApplication(void) UIApplication *__nullable RCTSharedApplication(void)
{ {
if (RCTRunningInAppExtension()) { if (RCTRunningInAppExtension()) {
return nil; return nil;
} }
return [[UIApplication class] performSelector:@selector(sharedApplication)]; return [[UIApplication class] performSelector:@selector(sharedApplication)];
} }


UIWindow *RCTKeyWindow(void) UIWindow *__nullable RCTKeyWindow(void)
{ {
if (RCTRunningInAppExtension()) { if (RCTRunningInAppExtension()) {
return nil; return nil;
Expand All @@ -390,11 +397,11 @@ BOOL RCTRunningInAppExtension(void)
return RCTSharedApplication().keyWindow; return RCTSharedApplication().keyWindow;
} }


UIAlertView *RCTAlertView(NSString *title, UIAlertView *__nullable RCTAlertView(NSString *title,
NSString *message, NSString *__nullable message,
id delegate, id __nullable delegate,
NSString *cancelButtonTitle, NSString *__nullable cancelButtonTitle,
NSArray<NSString *> *otherButtonTitles) NSArray<NSString *> *__nullable otherButtonTitles)
{ {
if (RCTRunningInAppExtension()) { if (RCTRunningInAppExtension()) {
RCTLogError(@"RCTAlertView is unavailable when running in an app extension"); RCTLogError(@"RCTAlertView is unavailable when running in an app extension");
Expand All @@ -421,12 +428,12 @@ BOOL RCTRunningInAppExtension(void)
return [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo]; return [[NSError alloc] initWithDomain:RCTErrorDomain code:0 userInfo:errorInfo];
} }


id RCTNullIfNil(id value) id RCTNullIfNil(id __nullable value)
{ {
return value ?: (id)kCFNull; return value ?: (id)kCFNull;
} }


id RCTNilIfNull(id value) id __nullable RCTNilIfNull(id __nullable value)
{ {
return value == (id)kCFNull ? nil : value; return value == (id)kCFNull ? nil : value;
} }
Expand All @@ -443,14 +450,14 @@ RCT_EXTERN double RCTZeroIfNaN(double value)
[data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]]; [data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];
} }


BOOL RCTIsGzippedData(NSData *); // exposed for unit testing purposes BOOL RCTIsGzippedData(NSData *__nullable); // exposed for unit testing purposes
BOOL RCTIsGzippedData(NSData *data) BOOL RCTIsGzippedData(NSData *__nullable data)
{ {
UInt8 *bytes = (UInt8 *)data.bytes; UInt8 *bytes = (UInt8 *)data.bytes;
return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
} }


NSData *RCTGzipData(NSData *input, float level) NSData *RCTGzipData(NSData *__nullable input, float level)
{ {
if (input.length == 0 || RCTIsGzippedData(input)) { if (input.length == 0 || RCTIsGzippedData(input)) {
return input; return input;
Expand Down Expand Up @@ -493,7 +500,7 @@ BOOL RCTIsGzippedData(NSData *data)
return output; return output;
} }


NSString *RCTBundlePathForURL(NSURL *URL) NSString *__nullable RCTBundlePathForURL(NSURL *__nullable URL)
{ {
if (!URL.fileURL) { if (!URL.fileURL) {
// Not a file path // Not a file path
Expand All @@ -512,7 +519,7 @@ BOOL RCTIsGzippedData(NSData *data)
return path; return path;
} }


BOOL RCTIsXCAssetURL(NSURL *imageURL) BOOL RCTIsXCAssetURL(NSURL *__nullable imageURL)
{ {
NSString *name = RCTBundlePathForURL(imageURL); NSString *name = RCTBundlePathForURL(imageURL);
if (name.pathComponents.count != 1) { if (name.pathComponents.count != 1) {
Expand Down Expand Up @@ -598,7 +605,7 @@ static void RCTGetRGBAColorComponents(CGColorRef color, CGFloat rgba[4])
return UIKitBundle ? [UIKitBundle localizedStringForKey:string value:string table:nil] : string; return UIKitBundle ? [UIKitBundle localizedStringForKey:string value:string table:nil] : string;
} }


NSString *RCTGetURLQueryParam(NSURL *URL, NSString *param) NSString *__nullable RCTGetURLQueryParam(NSURL *__nullable URL, NSString *param)
{ {
RCTAssertParam(param); RCTAssertParam(param);
if (!URL) { if (!URL) {
Expand All @@ -618,7 +625,7 @@ static void RCTGetRGBAColorComponents(CGColorRef color, CGFloat rgba[4])
return nil; return nil;
} }


NSURL *RCTURLByReplacingQueryParam(NSURL *URL, NSString *param, NSString *value) NSURL *__nullable RCTURLByReplacingQueryParam(NSURL *__nullable URL, NSString *param, NSString *__nullable value)
{ {
RCTAssertParam(param); RCTAssertParam(param);
if (!URL) { if (!URL) {
Expand Down

0 comments on commit 34d5fa2

Please sign in to comment.