Browse Source

Merge pull request #178 from tikoyesayan/master

Fix crash in FLEXRuntimeUtility
Ryan Olson 6 years ago
parent
commit
99eccdf4c3

+ 1 - 1
Classes/Editing/ArgumentInputViews/FLEXArgumentInputView.m

@@ -22,7 +22,7 @@
 {
     self = [super initWithFrame:CGRectZero];
     if (self) {
-        self.typeEncoding = @(typeEncoding);
+        self.typeEncoding = typeEncoding != NULL ? @(typeEncoding) : nil;
     }
     return self;
 }

+ 14 - 6
Classes/Utility/FLEXRuntimeUtility.m

@@ -277,14 +277,22 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     NSMutableArray *components = [NSMutableArray array];
     
     NSString *selectorName = NSStringFromSelector(method_getName(method));
-    NSArray *selectorComponents = [selectorName componentsSeparatedByString:@":"];
-    unsigned int numberOfArguments = method_getNumberOfArguments(method);
+    NSMutableArray *selectorComponents = [[selectorName componentsSeparatedByString:@":"] mutableCopy];
     
-    for (unsigned int argIndex = kFLEXNumberOfImplicitArgs; argIndex < numberOfArguments; argIndex++) {
-        char *argType = method_copyArgumentType(method, argIndex);
-        NSString *readableArgType = [self readableTypeForEncoding:@(argType)];
+    // this is a workaround cause method_getNumberOfArguments() returns wrong number for some methods
+    if (selectorComponents.count == 1) {
+        return [selectorComponents copy];
+    }
+    
+    if ([selectorComponents.lastObject isEqualToString:@""]) {
+        [selectorComponents removeLastObject];
+    }
+    
+    for (unsigned int argIndex = 0; argIndex < selectorComponents.count; argIndex++) {
+        char *argType = method_copyArgumentType(method, argIndex + kFLEXNumberOfImplicitArgs);
+        NSString *readableArgType = (argType != NULL) ? [self readableTypeForEncoding:@(argType)] : nil;
         free(argType);
-        NSString *prettyComponent = [NSString stringWithFormat:@"%@:(%@) ", [selectorComponents objectAtIndex:argIndex - kFLEXNumberOfImplicitArgs], readableArgType];
+        NSString *prettyComponent = [NSString stringWithFormat:@"%@:(%@) ", [selectorComponents objectAtIndex:argIndex], readableArgType];
         [components addObject:prettyComponent];
     }
     

+ 116 - 0
FLEX.xcodeproj/project.pbxproj

@@ -8,6 +8,8 @@
 
 /* Begin PBXBuildFile section */
 		04F1CA191C137CF1000A52B0 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 04F1CA181C137CF1000A52B0 /* LICENSE */; };
+		1C27A8B91F0E5A0400F0D02D /* FLEXTestsMethodsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */; };
+		1C27A8BB1F0E5A0400F0D02D /* FLEX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4C941F1B5B20570088C3F2 /* FLEX.framework */; };
 		222C88221C7339DC007CA15F /* FLEXRealmDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 222C88211C7339DC007CA15F /* FLEXRealmDefines.h */; };
 		224D49A81C673AB5000EAB86 /* FLEXRealmDatabaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 224D49A41C673AB5000EAB86 /* FLEXRealmDatabaseManager.h */; };
 		224D49A91C673AB5000EAB86 /* FLEXRealmDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 224D49A51C673AB5000EAB86 /* FLEXRealmDatabaseManager.m */; };
@@ -166,8 +168,21 @@
 		94AAF03A1BAF2F0300DE8760 /* FLEXKeyboardShortcutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 942DCD821BAE0AD300DB5DC2 /* FLEXKeyboardShortcutManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
+/* Begin PBXContainerItemProxy section */
+		1C27A8BC1F0E5A0400F0D02D /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 3A4C94161B5B20570088C3F2 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 3A4C941E1B5B20570088C3F2;
+			remoteInfo = FLEX;
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXFileReference section */
 		04F1CA181C137CF1000A52B0 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+		1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FLEXTestsMethodsList.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLEXTestsMethodsList.m; sourceTree = "<group>"; };
+		1C27A8BA1F0E5A0400F0D02D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		222C88211C7339DC007CA15F /* FLEXRealmDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDefines.h; sourceTree = "<group>"; };
 		224D49A41C673AB5000EAB86 /* FLEXRealmDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLEXRealmDatabaseManager.h; sourceTree = "<group>"; };
 		224D49A51C673AB5000EAB86 /* FLEXRealmDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLEXRealmDatabaseManager.m; sourceTree = "<group>"; };
@@ -330,6 +345,14 @@
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+		1C27A8B31F0E5A0300F0D02D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1C27A8BB1F0E5A0400F0D02D /* FLEX.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		3A4C941B1B5B20570088C3F2 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -342,10 +365,20 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		1C27A8B71F0E5A0400F0D02D /* FLEXTestsMethodsList */ = {
+			isa = PBXGroup;
+			children = (
+				1C27A8B81F0E5A0400F0D02D /* FLEXTestsMethodsList.m */,
+				1C27A8BA1F0E5A0400F0D02D /* Info.plist */,
+			);
+			path = FLEXTestsMethodsList;
+			sourceTree = "<group>";
+		};
 		3A4C94151B5B20570088C3F2 = {
 			isa = PBXGroup;
 			children = (
 				3A4C94211B5B20570088C3F2 /* FLEX */,
+				1C27A8B71F0E5A0400F0D02D /* FLEXTestsMethodsList */,
 				3A4C95451B5B216C0088C3F2 /* Frameworks */,
 				3A4C94201B5B20570088C3F2 /* Products */,
 			);
@@ -355,6 +388,7 @@
 			isa = PBXGroup;
 			children = (
 				3A4C941F1B5B20570088C3F2 /* FLEX.framework */,
+				1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -738,6 +772,24 @@
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
+		1C27A8B51F0E5A0300F0D02D /* FLEXTestsMethodsList */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTestsMethodsList" */;
+			buildPhases = (
+				1C27A8B21F0E5A0300F0D02D /* Sources */,
+				1C27A8B31F0E5A0300F0D02D /* Frameworks */,
+				1C27A8B41F0E5A0300F0D02D /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				1C27A8BD1F0E5A0400F0D02D /* PBXTargetDependency */,
+			);
+			name = FLEXTestsMethodsList;
+			productName = FLEXTestsMethodsList;
+			productReference = 1C27A8B61F0E5A0300F0D02D /* FLEXTestsMethodsList.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 		3A4C941E1B5B20570088C3F2 /* FLEX */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 3A4C94351B5B20570088C3F2 /* Build configuration list for PBXNativeTarget "FLEX" */;
@@ -784,11 +836,19 @@
 			projectRoot = "";
 			targets = (
 				3A4C941E1B5B20570088C3F2 /* FLEX */,
+				1C27A8B51F0E5A0300F0D02D /* FLEXTestsMethodsList */,
 			);
 		};
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
+		1C27A8B41F0E5A0300F0D02D /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		3A4C941D1B5B20570088C3F2 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -800,6 +860,14 @@
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
+		1C27A8B21F0E5A0300F0D02D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1C27A8B91F0E5A0400F0D02D /* FLEXTestsMethodsList.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		3A4C941A1B5B20570088C3F2 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -884,7 +952,46 @@
 		};
 /* End PBXSourcesBuildPhase section */
 
+/* Begin PBXTargetDependency section */
+		1C27A8BD1F0E5A0400F0D02D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 3A4C941E1B5B20570088C3F2 /* FLEX */;
+			targetProxy = 1C27A8BC1F0E5A0400F0D02D /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
 /* Begin XCBuildConfiguration section */
+		1C27A8BE1F0E5A0400F0D02D /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEVELOPMENT_TEAM = U3LST7M92S;
+				INFOPLIST_FILE = FLEXTestsMethodsList/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEXTestsMethodsList;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		1C27A8BF1F0E5A0400F0D02D /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				DEVELOPMENT_TEAM = U3LST7M92S;
+				INFOPLIST_FILE = FLEXTestsMethodsList/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.flipboard.FLEXTestsMethodsList;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
 		3A4C94331B5B20570088C3F2 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1037,6 +1144,15 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+		1C27A8C01F0E5A0400F0D02D /* Build configuration list for PBXNativeTarget "FLEXTestsMethodsList" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1C27A8BE1F0E5A0400F0D02D /* Debug */,
+				1C27A8BF1F0E5A0400F0D02D /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		3A4C94191B5B20570088C3F2 /* Build configuration list for PBXProject "FLEX" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

+ 119 - 0
FLEXTestsMethodsList/FLEXTestsMethodsList.m

@@ -0,0 +1,119 @@
+//
+//  FLEXTestMethodList.m
+//  FLEXTestMethodList
+//
+//  Created by Tigran Yesayan on 7/6/17.
+//  Copyright © 2017 Flipboard. All rights reserved.
+//
+
+#import <XCTest/XCTest.h>
+#import "FLEXRuntimeUtility.h"
+#import "FLEXManager.h"
+#import "FLEXWindow.h"
+#import "FLEXMultiColumnTableView.h"
+
+@interface FLEXRuntimeUtility (Testing)
+
++ (NSString *)readableTypeForEncoding:(NSString *)encodingString;
+
+@end
+
+@interface FLEXTestMethodList : XCTestCase
+
+@end
+
+@implementation FLEXTestMethodList
+
+- (void)setUp {
+    [super setUp];
+    // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown {
+    // Put teardown code here. This method is called after the invocation of each test method in the class.
+    [super tearDown];
+}
+
+- (void)testExample {
+    // This is an example of a functional test case.
+    // Use XCTAssert and related functions to verify your tests produce the correct results.
+    [self testMethodListForClass:[NSObject class]];
+    [self testMethodListForClass:[NSArray class]];
+    [self testMethodListForClass:[UIApplication class]];
+    [self testMethodListForClass:[UIView class]];
+    [self testMethodListForClass:[NSThread class]];
+    [self testMethodListForClass:[CALayer class]];
+    [self testMethodListForClass:[NSDictionary class]];
+    [self testMethodListForClass:[NSProxy class]];
+    [self testMethodListForClass:[NSData class]];
+    [self testMethodListForClass:[FLEXManager class]];
+    [self testMethodListForClass:[FLEXWindow class]];
+    [self testMethodListForClass:[FLEXMultiColumnTableView class]];
+    [self testMethodListForClass:[NSString class]];
+    [self testMethodListForClass:[NSSet class]];
+    [self testMethodListForClass:[NSUndoManager class]];
+    [self testMethodListForClass:[NSMutableArray class]];
+    [self testMethodListForClass:[NSMutableDictionary class]];
+    [self testMethodListForClass:[NSException class]];
+    [self testMethodListForClass:[UIImage class]];
+    [self testMethodListForClass:[UIViewController class]];
+    [self testMethodListForClass:[UIScreen class]];
+    [self testMethodListForClass:[UIResponder class]];
+    [self testMethodListForClass:[NSNumber class]];
+    [self testMethodListForClass:[NSValue class]];
+    [self testMethodListForClass:[NSError class]];
+    [self testMethodListForClass:[NSNotificationCenter class]];
+    [self testMethodListForClass:[NSUserActivity class]];
+    [self testMethodListForClass:[NSUserDefaults class]];
+    [self testMethodListForClass:[NSExpression class]];
+    [self testMethodListForClass:[NSBundle class]];
+}
+
+- (void)testMethodListForClass:(Class)class {
+    NSLog(@"class: %@", NSStringFromClass(class));
+    unsigned int methodCount = 0;
+    Method *methods = class_copyMethodList(class, &methodCount);
+    for (unsigned int i = 0; i < methodCount; ++i) {
+        Method method = methods[i];
+        NSString *selectorName = NSStringFromSelector(method_getName(method));
+        NSArray *prevWay = [self prettyArgumentComponentsForMethod:method];
+        if (![prevWay count]) {
+            prevWay = @[ selectorName ];
+        }
+        
+        NSArray *newWay = [FLEXRuntimeUtility prettyArgumentComponentsForMethod:method];
+        
+        XCTAssert([newWay isEqual:prevWay]);
+    }
+    
+    free(methods);
+}
+
+- (void)testPerformanceExample {
+    // This is an example of a performance test case.
+    [self measureBlock:^{
+        // Put the code you want to measure the time of here.
+    }];
+}
+
+#pragma mark - Method to test with
+
+- (NSArray *)prettyArgumentComponentsForMethod:(Method)method {
+    NSMutableArray *components = [NSMutableArray array];
+    
+    NSString *selectorName = NSStringFromSelector(method_getName(method));
+    NSArray *selectorComponents = [selectorName componentsSeparatedByString:@":"];
+    unsigned int numberOfArguments = method_getNumberOfArguments(method);
+    
+    for (unsigned int argIndex = kFLEXNumberOfImplicitArgs; argIndex < numberOfArguments; argIndex++) {
+        char *argType = method_copyArgumentType(method, argIndex);
+        NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)];
+        free(argType);
+        NSString *prettyComponent = [NSString stringWithFormat:@"%@:(%@) ", [selectorComponents objectAtIndex:argIndex - kFLEXNumberOfImplicitArgs], readableArgType];
+        [components addObject:prettyComponent];
+    }
+    
+    return components;
+}
+
+@end

+ 22 - 0
FLEXTestsMethodsList/Info.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>