Просмотр исходного кода

Adopt FLEXTypeEncodingParser

Debugging will be soooo much less frustrating now that we aren't throwing exceptions all over the place.

Also, we no longer load pre-registered shortcuts in testing environments. This may come back to bite me in the butt if it turns out the XCTest class exists in UI tests or something.
Tanner Bennett лет назад: 6
Родитель
Сommit
99d2ddd001

+ 4 - 19
Classes/Editing/ArgumentInputViews/FLEXArgumentInputStructView.m

@@ -9,6 +9,7 @@
 #import "FLEXArgumentInputStructView.h"
 #import "FLEXArgumentInputStructView.h"
 #import "FLEXArgumentInputViewFactory.h"
 #import "FLEXArgumentInputViewFactory.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeUtility.h"
+#import "FLEXTypeEncodingParser.h"
 
 
 @interface FLEXArgumentInputStructView ()
 @interface FLEXArgumentInputStructView ()
 
 
@@ -63,12 +64,8 @@
         const char *structTypeEncoding = [inputValue objCType];
         const char *structTypeEncoding = [inputValue objCType];
         if (strcmp(self.typeEncoding.UTF8String, structTypeEncoding) == 0) {
         if (strcmp(self.typeEncoding.UTF8String, structTypeEncoding) == 0) {
             NSUInteger valueSize = 0;
             NSUInteger valueSize = 0;
-            @try {
-                // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-                NSGetSizeAndAlignment(structTypeEncoding, &valueSize, NULL);
-            } @catch (NSException *exception) { }
             
             
-            if (valueSize > 0) {
+            if (FLEXGetSizeAndAlignment(structTypeEncoding, &valueSize, NULL)) {
                 void *unboxedValue = malloc(valueSize);
                 void *unboxedValue = malloc(valueSize);
                 [inputValue getValue:unboxedValue];
                 [inputValue getValue:unboxedValue];
                 [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
                 [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
@@ -97,12 +94,8 @@
     NSValue *boxedStruct = nil;
     NSValue *boxedStruct = nil;
     const char *structTypeEncoding = self.typeEncoding.UTF8String;
     const char *structTypeEncoding = self.typeEncoding.UTF8String;
     NSUInteger structSize = 0;
     NSUInteger structSize = 0;
-    @try {
-        // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-        NSGetSizeAndAlignment(structTypeEncoding, &structSize, NULL);
-    } @catch (NSException *exception) { }
     
     
-    if (structSize > 0) {
+    if (FLEXGetSizeAndAlignment(structTypeEncoding, &structSize, NULL)) {
         void *unboxedStruct = malloc(structSize);
         void *unboxedStruct = malloc(structSize);
         [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
         [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
                                                                                            const char *fieldTypeEncoding,
                                                                                            const char *fieldTypeEncoding,
@@ -182,15 +175,7 @@
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value {
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value {
     NSParameterAssert(type);
     NSParameterAssert(type);
     if (type[0] == FLEXTypeEncodingStructBegin) {
     if (type[0] == FLEXTypeEncodingStructBegin) {
-        // We cannot support anything with bitfields or structs,
-        // and this will throw an exception if it does
-        @try {
-            NSGetSizeAndAlignment(type, nil, nil);
-        } @catch (NSException *exception) {
-            return NO;
-        }
-
-        return YES;
+        return FLEXGetSizeAndAlignment(type, nil, nil);
     }
     }
 
 
     return NO;
     return NO;

+ 10 - 7
Classes/ObjectExplorers/Sections/Shortcuts/FLEXShortcutsFactory+Defaults.m

@@ -10,11 +10,14 @@
 #import "FLEXShortcut.h"
 #import "FLEXShortcut.h"
 #import <objc/runtime.h>
 #import <objc/runtime.h>
 
 
+// Don't load pre-registered shortcuts in a test environment
+#define FLEX_EXIT_IF_TESTING() if (NSClassFromString(@"XCTest")) return;
+
 #pragma mark - Views
 #pragma mark - Views
 
 
 @implementation FLEXShortcutsFactory (Views)
 @implementation FLEXShortcutsFactory (Views)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     // Only available since iOS 3.2, but we never supported iOS 3, so who cares
     // Only available since iOS 3.2, but we never supported iOS 3, so who cares
     NSArray *ivars = @[@"_gestureRecognizers"];
     NSArray *ivars = @[@"_gestureRecognizers"];
     NSArray *methods = @[@"sizeToFit", @"setNeedsLayout", @"removeFromSuperview"];
     NSArray *methods = @[@"sizeToFit", @"setNeedsLayout", @"removeFromSuperview"];
@@ -73,7 +76,7 @@
 
 
 @implementation FLEXShortcutsFactory (ViewControllers)
 @implementation FLEXShortcutsFactory (ViewControllers)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     // UIViewController
     // UIViewController
     self.append
     self.append
         .properties(@[
         .properties(@[
@@ -90,7 +93,7 @@
 
 
 @implementation FLEXShortcutsFactory (UIImage)
 @implementation FLEXShortcutsFactory (UIImage)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[
     self.append.methods(@[
         @"CGImage", @"CIImage"
         @"CGImage", @"CIImage"
     ]).properties(@[
     ]).properties(@[
@@ -110,7 +113,7 @@
 
 
 @implementation FLEXShortcutsFactory (NSBundle)
 @implementation FLEXShortcutsFactory (NSBundle)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.properties(@[
     self.append.properties(@[
         @"bundleIdentifier", @"principalClass",
         @"bundleIdentifier", @"principalClass",
         @"infoDictionary", @"bundlePath",
         @"infoDictionary", @"bundlePath",
@@ -125,7 +128,7 @@
 
 
 @implementation FLEXShortcutsFactory (Classes)
 @implementation FLEXShortcutsFactory (Classes)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[@"new", @"alloc"]).forClass(objc_getMetaClass("NSObject"));
     self.append.methods(@[@"new", @"alloc"]).forClass(objc_getMetaClass("NSObject"));
 }
 }
 
 
@@ -136,7 +139,7 @@
 
 
 @implementation FLEXShortcutsFactory (Activities)
 @implementation FLEXShortcutsFactory (Activities)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.properties(@[
     self.append.properties(@[
         @"item", @"placeholderItem", @"activityType"
         @"item", @"placeholderItem", @"activityType"
     ]).forClass(UIActivityItemProvider.class);
     ]).forClass(UIActivityItemProvider.class);
@@ -153,7 +156,7 @@
 
 
 @implementation FLEXShortcutsFactory (Blocks)
 @implementation FLEXShortcutsFactory (Blocks)
 
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[@"invoke"]).forClass(NSClassFromString(@"NSBlock"));
     self.append.methods(@[@"invoke"]).forClass(NSClassFromString(@"NSBlock"));
 }
 }
 
 

+ 1 - 0
Classes/Utility/FLEXUtility.h

@@ -11,6 +11,7 @@
 #import <Foundation/Foundation.h>
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 #import <objc/runtime.h>
 #import <objc/runtime.h>
+#import "FLEXTypeEncodingParser.h"
 #import "FLEXAlert.h"
 #import "FLEXAlert.h"
 #import "NSArray+Functional.h"
 #import "NSArray+Functional.h"
 #import "UIFont+FLEX.h"
 #import "UIFont+FLEX.h"

+ 3 - 9
Classes/Utility/Runtime/FLEXIvar.m

@@ -10,6 +10,7 @@
 #import "FLEXIvar.h"
 #import "FLEXIvar.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeSafety.h"
 #import "FLEXRuntimeSafety.h"
+#import "FLEXTypeEncodingParser.h"
 
 
 @interface FLEXIvar () {
 @interface FLEXIvar () {
     NSString *_flex_description;
     NSString *_flex_description;
@@ -71,9 +72,7 @@
     _type         = (FLEXTypeEncoding)[_typeEncoding characterAtIndex:0];
     _type         = (FLEXTypeEncoding)[_typeEncoding characterAtIndex:0];
     _offset       = ivar_getOffset(self.objc_ivar);
     _offset       = ivar_getOffset(self.objc_ivar);
 
 
-    @try {
-        NSGetSizeAndAlignment(_typeEncoding.UTF8String, &_size, nil);
-    } @catch (NSException *exception) { }
+    FLEXGetSizeAndAlignment(_typeEncoding.UTF8String, &_size, nil);
     _details = [NSString stringWithFormat:
     _details = [NSString stringWithFormat:
         @"%@ bytes, offset %@  —  %@",
         @"%@ bytes, offset %@  —  %@",
         (_size ? @(_size) : @"?"), @(_offset), _typeEncoding
         (_size ? @(_size) : @"?"), @(_offset), _typeEncoding
@@ -121,12 +120,7 @@
         );
         );
 
 
         NSUInteger bufferSize = 0;
         NSUInteger bufferSize = 0;
-        @try {
-            // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-            NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
-        } @catch (NSException *exception) { }
-
-        if (bufferSize > 0) {
+        if (FLEXGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL)) {
             void *buffer = calloc(bufferSize, 1);
             void *buffer = calloc(bufferSize, 1);
             [valueValue getValue:buffer];
             [valueValue getValue:buffer];
             void *pointer = (__bridge void *)target + self.offset;
             void *pointer = (__bridge void *)target + self.offset;

+ 7 - 4
Classes/Utility/Runtime/FLEXMethod.m

@@ -9,7 +9,7 @@
 
 
 #import "FLEXMethod.h"
 #import "FLEXMethod.h"
 #import "FLEXMirror.h"
 #import "FLEXMirror.h"
-
+#import "FLEXTypeEncodingParser.h"
 
 
 @implementation FLEXMethod
 @implementation FLEXMethod
 @dynamic implementation;
 @dynamic implementation;
@@ -67,10 +67,9 @@
         _objc_method = method;
         _objc_method = method;
         _isInstanceMethod = isInstanceMethod;
         _isInstanceMethod = isInstanceMethod;
         _signatureString = @(method_getTypeEncoding(method));
         _signatureString = @(method_getTypeEncoding(method));
-        @try {
+        
+        if ([FLEXTypeEncodingParser methodTypeEncodingSupported:_signatureString]) {
             _signature = [NSMethodSignature signatureWithObjCTypes:_signatureString.UTF8String];
             _signature = [NSMethodSignature signatureWithObjCTypes:_signatureString.UTF8String];
-        } @catch (NSException *exception) {
-            _signature = nil;
         }
         }
 
 
         [self examine];
         [self examine];
@@ -349,6 +348,10 @@
 
 
 // Code borrowed from MAObjcRuntime, by Mike Ash.
 // Code borrowed from MAObjcRuntime, by Mike Ash.
 - (void)getReturnValue:(void *)retPtr forMessageSend:(id)target arguments:(va_list)args {
 - (void)getReturnValue:(void *)retPtr forMessageSend:(id)target arguments:(va_list)args {
+    if (!_signature) {
+        return;
+    }
+    
     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:_signature];
     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:_signature];
     NSUInteger argumentCount = _signature.numberOfArguments;
     NSUInteger argumentCount = _signature.numberOfArguments;
     
     

+ 15 - 18
Classes/Utility/Runtime/FLEXRuntimeUtility.m

@@ -9,6 +9,7 @@
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXObjcInternal.h"
 #import "FLEXObjcInternal.h"
+#import "FLEXTypeEncodingParser.h"
 
 
 // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6
 // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6
 NSString *const kFLEXPropertyAttributeKeyTypeEncoding = @"T";
 NSString *const kFLEXPropertyAttributeKeyTypeEncoding = @"T";
@@ -296,13 +297,12 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
         return nil;
         return nil;
     }
     }
 
 
-    // Probably an unsupported type encoding, like bitfields
-    // or inline arrays. In the future, we could calculate
-    // the return length on our own. For now, we abort.
+    // Probably an unsupported type encoding, like bitfields.
+    // In the future, we could calculate the return length
+    // on our own. For now, we abort.
     //
     //
     // For future reference, the code here will get the true type encoding.
     // For future reference, the code here will get the true type encoding.
     // NSMethodSignature will convert {?=b8b4b1b1b18[8S]} to {?}
     // NSMethodSignature will convert {?=b8b4b1b1b18[8S]} to {?}
-    // A solution might involve hooking NSGetSizeAndAlignment.
     //
     //
     // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector));
     // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector));
     NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector];
     NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector];
@@ -361,9 +361,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
 
 
                 @try {
                 @try {
                     NSUInteger bufferSize = 0;
                     NSUInteger bufferSize = 0;
-
-                    // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-                    NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
+                    FLEXGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
 
 
                     if (bufferSize > 0) {
                     if (bufferSize > 0) {
                         void *buffer = alloca(bufferSize);
                         void *buffer = alloca(bufferSize);
@@ -568,30 +566,29 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
                 substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)
                 substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)
             ];
             ];
 
 
-            NSUInteger fieldAlignment = 0;
-            NSUInteger structSize = 0;
-            @try {
-                // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-                NSGetSizeAndAlignment(structEncoding, &structSize, &fieldAlignment);
-            } @catch (NSException *exception) { }
-
-            if (structSize > 0) {
+            NSUInteger fieldAlignment = 0, structSize = 0;
+            if (FLEXGetSizeAndAlignment(structEncoding, &structSize, &fieldAlignment)) {
                 NSUInteger runningFieldIndex = 0;
                 NSUInteger runningFieldIndex = 0;
                 NSUInteger runningFieldOffset = 0;
                 NSUInteger runningFieldOffset = 0;
                 const char *typeStart = equals + 1;
                 const char *typeStart = equals + 1;
+                
                 while (*typeStart != FLEXTypeEncodingStructEnd) {
                 while (*typeStart != FLEXTypeEncodingStructEnd) {
                     NSUInteger fieldSize = 0;
                     NSUInteger fieldSize = 0;
-                    // If the struct type encoding was successfully handled by NSGetSizeAndAlignment above, we *should* be ok with the field here.
+                    // If the struct type encoding was successfully handled by
+                    // FLEXGetSizeAndAlignment above, we *should* be ok with the field here.
                     const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL);
                     const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL);
                     NSString *typeEncoding = [@(structEncoding)
                     NSString *typeEncoding = [@(structEncoding)
                         substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)
                         substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)
                     ];
                     ];
-                    // Padding to keep proper alignment. __attribute((packed)) structs will break here.
-                    // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those.
+                    
+                    // Padding to keep proper alignment. __attribute((packed)) structs
+                    // will break here. The type encoding is no different for packed structs,
+                    // so it's not clear there's anything we can do for those.
                     const NSUInteger currentSizeSum = runningFieldOffset % fieldAlignment;
                     const NSUInteger currentSizeSum = runningFieldOffset % fieldAlignment;
                     if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) {
                     if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) {
                         runningFieldOffset += fieldAlignment - currentSizeSum;
                         runningFieldOffset += fieldAlignment - currentSizeSum;
                     }
                     }
+                    
                     typeBlock(
                     typeBlock(
                         structName,
                         structName,
                         typeEncoding.UTF8String,
                         typeEncoding.UTF8String,