Przeglądaj źródła

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 lat temu
rodzic
commit
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,