Fix non-exported module warnings for superclasses

Reviewed By: mhorowitz

Differential Revision: D3841655

fbshipit-source-id: b855f9bef6c53a0964c59e1977e5eb23452edce3
This commit is contained in:
Pieter De Baets 2016-09-19 04:43:06 -07:00 committed by Facebook Github Bot 2
parent fd84447341
commit bd4cd6ea5d
3 changed files with 54 additions and 33 deletions

View File

@ -40,8 +40,6 @@ typedef NS_ENUM(NSUInteger, RCTBridgeFields) {
RCTBridgeFieldCallID,
};
RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
@implementation RCTBatchedBridge
{
BOOL _wasBatchActive;
@ -265,38 +263,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)dele
extraModules = self.moduleProvider();
}
#if RCT_DEBUG
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (RCT_DEBUG && !RCTRunningInTestEnvironment()) {
// Check for unexported modules
Class *classes;
unsigned int classCount;
classes = objc_copyClassList(&classCount);
NSMutableSet *moduleClasses = [NSMutableSet new];
[moduleClasses addObjectsFromArray:RCTGetModuleClasses()];
[moduleClasses addObjectsFromArray:[extraModules valueForKeyPath:@"class"]];
for (unsigned int i = 0; i < classCount; i++)
{
Class cls = classes[i];
Class superclass = cls;
while (superclass)
{
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
{
if (![moduleClasses containsObject:cls] &&
![cls respondsToSelector:@selector(moduleName)]) {
RCTLogWarn(@"Class %@ was not exported. Did you forget to use "
"RCT_EXPORT_MODULE()?", cls);
}
break;
}
superclass = class_getSuperclass(superclass);
}
}
}
RCTVerifyAllModulesExported(extraModules);
});
#endif
NSMutableArray<Class> *moduleClassesByID = [NSMutableArray new];
NSMutableArray<RCTModuleData *> *moduleDataByID = [NSMutableArray new];

View File

@ -12,6 +12,12 @@
@class RCTModuleData;
@protocol RCTJavaScriptExecutor;
RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
#if RCT_DEBUG
RCT_EXTERN void RCTVerifyAllModulesExported(NSArray *extraModules);
#endif
@interface RCTBridge ()
// Private designated initializer

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTBridge.h"
#import "RCTBridge+Private.h"
#import <objc/runtime.h>
@ -27,7 +28,6 @@ NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailT
NSString *const RCTDidInitializeModuleNotification = @"RCTDidInitializeModuleNotification";
static NSMutableArray<Class> *RCTModuleClasses;
NSArray<Class> *RCTGetModuleClasses(void);
NSArray<Class> *RCTGetModuleClasses(void)
{
return RCTModuleClasses;
@ -58,7 +58,7 @@ void RCTRegisterModule(Class moduleClass)
*/
NSString *RCTBridgeModuleNameForClass(Class cls)
{
#if RCT_DEV
#if RCT_DEBUG
RCTAssert([cls conformsToProtocol:@protocol(RCTBridgeModule)],
@"Bridge module `%@` does not conform to RCTBridgeModule", cls);
#endif
@ -73,6 +73,49 @@ NSString *RCTBridgeModuleNameForClass(Class cls)
return name;
}
#if RCT_DEBUG
void RCTVerifyAllModulesExported(NSArray *extraModules)
{
// Check for unexported modules
unsigned int classCount;
Class *classes = objc_copyClassList(&classCount);
NSMutableSet *moduleClasses = [NSMutableSet new];
[moduleClasses addObjectsFromArray:RCTGetModuleClasses()];
[moduleClasses addObjectsFromArray:[extraModules valueForKeyPath:@"class"]];
for (unsigned int i = 0; i < classCount; i++) {
Class cls = classes[i];
Class superclass = cls;
while (superclass) {
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule))) {
if ([moduleClasses containsObject:cls]) {
break;
}
// Verify it's not a super-class of one of our moduleClasses
BOOL isModuleSuperClass = NO;
for (Class moduleClass in moduleClasses) {
if ([moduleClass isSubclassOfClass:cls]) {
isModuleSuperClass = YES;
break;
}
}
if (isModuleSuperClass) {
break;
}
RCTLogWarn(@"Class %@ was not exported. Did you forget to use RCT_EXPORT_MODULE()?", cls);
break;
}
superclass = class_getSuperclass(superclass);
}
}
free(classes);
}
#endif
@implementation RCTBridge
{
NSURL *_delegateBundleURL;