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

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 "FLEXArgumentInputViewFactory.h"
 #import "FLEXRuntimeUtility.h"
+#import "FLEXTypeEncodingParser.h"
 
 @interface FLEXArgumentInputStructView ()
 
@@ -63,12 +64,8 @@
         const char *structTypeEncoding = [inputValue objCType];
         if (strcmp(self.typeEncoding.UTF8String, structTypeEncoding) == 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);
                 [inputValue getValue:unboxedValue];
                 [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
@@ -97,12 +94,8 @@
     NSValue *boxedStruct = nil;
     const char *structTypeEncoding = self.typeEncoding.UTF8String;
     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);
         [FLEXRuntimeUtility enumerateTypesInStructEncoding:structTypeEncoding usingBlock:^(NSString *structName,
                                                                                            const char *fieldTypeEncoding,
@@ -182,15 +175,7 @@
 + (BOOL)supportsObjCType:(const char *)type withCurrentValue:(id)value {
     NSParameterAssert(type);
     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;

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

@@ -10,11 +10,14 @@
 #import "FLEXShortcut.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
 
 @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
     NSArray *ivars = @[@"_gestureRecognizers"];
     NSArray *methods = @[@"sizeToFit", @"setNeedsLayout", @"removeFromSuperview"];
@@ -73,7 +76,7 @@
 
 @implementation FLEXShortcutsFactory (ViewControllers)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     // UIViewController
     self.append
         .properties(@[
@@ -90,7 +93,7 @@
 
 @implementation FLEXShortcutsFactory (UIImage)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[
         @"CGImage", @"CIImage"
     ]).properties(@[
@@ -110,7 +113,7 @@
 
 @implementation FLEXShortcutsFactory (NSBundle)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.properties(@[
         @"bundleIdentifier", @"principalClass",
         @"infoDictionary", @"bundlePath",
@@ -125,7 +128,7 @@
 
 @implementation FLEXShortcutsFactory (Classes)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[@"new", @"alloc"]).forClass(objc_getMetaClass("NSObject"));
 }
 
@@ -136,7 +139,7 @@
 
 @implementation FLEXShortcutsFactory (Activities)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.properties(@[
         @"item", @"placeholderItem", @"activityType"
     ]).forClass(UIActivityItemProvider.class);
@@ -153,7 +156,7 @@
 
 @implementation FLEXShortcutsFactory (Blocks)
 
-+ (void)load {
++ (void)load { FLEX_EXIT_IF_TESTING()
     self.append.methods(@[@"invoke"]).forClass(NSClassFromString(@"NSBlock"));
 }
 

+ 1 - 0
Classes/Utility/FLEXUtility.h

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

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

@@ -10,6 +10,7 @@
 #import "FLEXIvar.h"
 #import "FLEXRuntimeUtility.h"
 #import "FLEXRuntimeSafety.h"
+#import "FLEXTypeEncodingParser.h"
 
 @interface FLEXIvar () {
     NSString *_flex_description;
@@ -71,9 +72,7 @@
     _type         = (FLEXTypeEncoding)[_typeEncoding characterAtIndex:0];
     _offset       = ivar_getOffset(self.objc_ivar);
 
-    @try {
-        NSGetSizeAndAlignment(_typeEncoding.UTF8String, &_size, nil);
-    } @catch (NSException *exception) { }
+    FLEXGetSizeAndAlignment(_typeEncoding.UTF8String, &_size, nil);
     _details = [NSString stringWithFormat:
         @"%@ bytes, offset %@  —  %@",
         (_size ? @(_size) : @"?"), @(_offset), _typeEncoding
@@ -121,12 +120,7 @@
         );
 
         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);
             [valueValue getValue:buffer];
             void *pointer = (__bridge void *)target + self.offset;

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

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

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

@@ -9,6 +9,7 @@
 #import <UIKit/UIKit.h>
 #import "FLEXRuntimeUtility.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
 NSString *const kFLEXPropertyAttributeKeyTypeEncoding = @"T";
@@ -296,13 +297,12 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
         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.
     // NSMethodSignature will convert {?=b8b4b1b1b18[8S]} to {?}
-    // A solution might involve hooking NSGetSizeAndAlignment.
     //
     // returnType = method_getTypeEncoding(class_getInstanceMethod([object class], selector));
     NSMethodSignature *methodSignature = [object methodSignatureForSelector:selector];
@@ -361,9 +361,7 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
 
                 @try {
                     NSUInteger bufferSize = 0;
-
-                    // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-                    NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
+                    FLEXGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
 
                     if (bufferSize > 0) {
                         void *buffer = alloca(bufferSize);
@@ -568,30 +566,29 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
                 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 runningFieldOffset = 0;
                 const char *typeStart = equals + 1;
+                
                 while (*typeStart != FLEXTypeEncodingStructEnd) {
                     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);
                     NSString *typeEncoding = [@(structEncoding)
                         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;
                     if (currentSizeSum != 0 && currentSizeSum + fieldSize > fieldAlignment) {
                         runningFieldOffset += fieldAlignment - currentSizeSum;
                     }
+                    
                     typeBlock(
                         structName,
                         typeEncoding.UTF8String,