Selaa lähdekoodia

Move methods from RuntimeUtility to metadata classes

Tanner Bennett 6 vuotta sitten
vanhempi
commit
11544b77b6

+ 6 - 7
Classes/Editing/FLEXFieldEditorViewController.m

@@ -29,7 +29,7 @@
 #pragma mark - Initialization
 
 + (instancetype)target:(id)target property:(FLEXProperty *)property {
-    id value = [FLEXRuntimeUtility valueForProperty:property.objc_property onObject:target];
+    id value = [property getValue:target];
     if (![self canEditProperty:property onObject:target currentValue:value]) {
         return nil;
     }
@@ -92,8 +92,7 @@
     } else {
         // TODO: check mutability and use mutableCopy if necessary;
         // this currently could and would assign NSArray to NSMutableArray
-
-        [FLEXRuntimeUtility setValue:self.firstInputView.inputValue forIvar:self.ivar.objc_ivar onObject:self.target];
+        [self.ivar setValue:self.firstInputView.inputValue onObject:self.target];
     }
 
     // Go back after setting, but not for switches.
@@ -120,9 +119,9 @@
 
 - (id)currentValue {
     if (self.property) {
-        return [FLEXRuntimeUtility valueForProperty:self.property.objc_property onObject:self.target];
+        return [self.property getValue:self.target];
     } else {
-        return [FLEXRuntimeUtility valueForIvar:self.ivar.objc_ivar onObject:self.target];
+        return [self.ivar getValue:self.target];
     }
 }
 
@@ -136,9 +135,9 @@
 
 - (NSString *)fieldDescription {
     if (self.property) {
-        return [FLEXRuntimeUtility fullDescriptionForProperty:self.property.objc_property];
+        return self.property.fullDescription;
     } else {
-        return [FLEXRuntimeUtility prettyNameForIvar:self.ivar.objc_ivar];
+        return self.ivar.description;
     }
 }
 

+ 0 - 2
Classes/Utility/FLEXUtility.h

@@ -38,8 +38,6 @@
 + (UIColor *)hierarchyIndentPatternColor;
 + (NSString *)applicationImageName;
 + (NSString *)applicationName;
-+ (NSString *)safeDescriptionForObject:(id)object;
-+ (NSString *)safeDebugDescriptionForObject:(id)object;
 + (NSString *)addressOfObject:(id)object;
 + (UIFont *)defaultFontOfSize:(CGFloat)size;
 + (UIFont *)defaultTableViewCellLabelFont;

+ 1 - 0
Classes/Utility/Runtime/FLEXIvar.h

@@ -33,6 +33,7 @@
 @property (nonatomic) id tag;
 
 - (id)getValue:(id)target;
+- (void)setValue:(id)value onObject:(id)target;
 
 /// Calls into -getValue: and passes that value into
 /// -[FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:type:]

+ 49 - 1
Classes/Utility/Runtime/FLEXIvar.m

@@ -72,7 +72,55 @@
 }
 
 - (id)getValue:(id)target {
-    return [FLEXRuntimeUtility valueForIvar:self.objc_ivar onObject:target];
+    id value = nil;
+#ifdef __arm64__
+    // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html
+    if (self.type == FLEXTypeEncodingObjcClass && [self.name isEqualToString:@"isa"]) {
+        value = object_getClass(target);
+    } else
+#endif
+    if (self.type == FLEXTypeEncodingObjcObject || self.type == FLEXTypeEncodingObjcClass) {
+        value = object_getIvar(target, self.objc_ivar);
+    } else {
+        void *pointer = (__bridge void *)target + self.offset;
+        value = [FLEXRuntimeUtility
+            valueForPrimitivePointer:pointer
+            objCType:self.typeEncoding.UTF8String
+        ];
+    }
+
+    return value;
+}
+
+- (void)setValue:(id)value onObject:(id)target {
+    const char *typeEncodingCString = self.typeEncoding.UTF8String;
+    if (self.type == FLEXTypeEncodingObjcObject) {
+        object_setIvar(target, self.objc_ivar, value);
+    } else if ([value isKindOfClass:[NSValue class]]) {
+        // Primitive - unbox the NSValue.
+        NSValue *valueValue = (NSValue *)value;
+
+        // Make sure that the box contained the correct type.
+        NSAssert(
+            strcmp(valueValue.objCType, typeEncodingCString) == 0,
+            @"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %@ on object: %@",
+            valueValue.objCType, typeEncodingCString, self.name, target
+        );
+
+        NSUInteger bufferSize = 0;
+        @try {
+            // NSGetSizeAndAlignment barfs on type encoding for bitfields.
+            NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
+        } @catch (NSException *exception) { }
+
+        if (bufferSize > 0) {
+            void *buffer = calloc(bufferSize, 1);
+            [valueValue getValue:buffer];
+            void *pointer = (__bridge void *)target + self.offset;
+            memcpy(pointer, buffer, bufferSize);
+            free(buffer);
+        }
+    }
 }
 
 - (id)getPotentiallyUnboxedValue:(id)target {

+ 16 - 24
Classes/Utility/Runtime/FLEXMethod.m

@@ -83,7 +83,7 @@
 
 - (NSString *)description {
     if (!_flex_description) {
-        _flex_description = [FLEXMethod prettyNameForMethod:self.objc_method isClassMethod:!_isInstanceMethod];
+        _flex_description = [self prettyName];
     }
     
     return _flex_description;
@@ -98,43 +98,35 @@
     return string;
 }
 
-+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod {
-    NSString *selectorName = NSStringFromSelector(method_getName(method));
-    NSString *methodTypeString = isClassMethod ? @"+" : @"-";
-    NSString *readableReturnType = ({
-        char *returnType = method_copyReturnType(method);
-        NSString *ret = [FLEXRuntimeUtility readableTypeForEncoding:@(returnType)];
-        free(returnType);
-        ret;
-    });
+- (NSString *)prettyName {
+    NSString *methodTypeString = self.isInstanceMethod ? @"-" : @"+";
+    NSString *readableReturnType = [FLEXRuntimeUtility readableTypeForEncoding:@(self.signature.methodReturnType ?: "")];
     
     NSString *prettyName = [NSString stringWithFormat:@"%@ (%@)", methodTypeString, readableReturnType];
-    NSArray *components = [self prettyArgumentComponentsForMethod:method];
+    NSArray *components = [self prettyArgumentComponents];
+
     if (components.count) {
-        prettyName = [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]];
+        return [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]];
     } else {
-        prettyName = [prettyName stringByAppendingString:selectorName];
+        return [prettyName stringByAppendingString:self.selectorString];
     }
-    
-    return prettyName;
 }
 
-+ (NSArray *)prettyArgumentComponentsForMethod:(Method)method {
-    NSMutableArray *components = [NSMutableArray array];
-    
-    NSString *selectorName = NSStringFromSelector(method_getName(method));
-    NSArray *selectorComponents = [selectorName componentsSeparatedByString:@":"];
-    unsigned int numberOfArguments = method_getNumberOfArguments(method);
+- (NSArray *)prettyArgumentComponents {
+    NSMutableArray *components = [NSMutableArray new];
+
+    NSArray *selectorComponents = [self.selectorString componentsSeparatedByString:@":"];
+    NSUInteger numberOfArguments = self.numberOfArguments;
     
-    for (unsigned int argIndex = 2; argIndex < numberOfArguments; argIndex++) {
-        char *argType = method_copyArgumentType(method, argIndex);
+    for (NSUInteger argIndex = 2; argIndex < numberOfArguments; argIndex++) {
+        const char *argType = [self.signature getArgumentTypeAtIndex:argIndex];
         NSString *readableArgType = [FLEXRuntimeUtility readableTypeForEncoding:@(argType)];
-        free(argType);
         NSString *prettyComponent = [NSString
             stringWithFormat:@"%@:(%@) ",
             selectorComponents[argIndex - 2],
             readableArgType
         ];
+
         [components addObject:prettyComponent];
     }
     

+ 3 - 0
Classes/Utility/Runtime/FLEXProperty.h

@@ -66,6 +66,9 @@
 @property (nonatomic) id tag;
 
 /// @return The value of this property on \c target as given by \c -valueForKey:
+/// A source-like description of the property, with all of its attributes.
+@property (nonatomic, readonly) NSString *fullDescription;
+
 - (id)getValue:(id)target;
 /// Calls into -getValue: and passes that value into
 /// -[FLEXRuntimeUtility potentiallyUnwrapBoxedPointer:type:]

+ 52 - 1
Classes/Utility/Runtime/FLEXProperty.m

@@ -156,8 +156,59 @@
     return _imageName;
 }
 
+- (NSString *)fullDescription {
+    NSMutableArray<NSString *> *attributesStrings = [NSMutableArray array];
+    FLEXPropertyAttributes *attributes = self.attributes;
+
+    // Atomicity
+    if (attributes.isNonatomic) {
+        [attributesStrings addObject:@"nonatomic"];
+    } else {
+        [attributesStrings addObject:@"atomic"];
+    }
+
+    // Storage
+    if (attributes.isRetained) {
+        [attributesStrings addObject:@"strong"];
+    } else if (attributes.isCopy) {
+        [attributesStrings addObject:@"copy"];
+    } else if (attributes.isWeak) {
+        [attributesStrings addObject:@"weak"];
+    } else {
+        [attributesStrings addObject:@"assign"];
+    }
+
+    // Mutability
+    if (attributes.isReadOnly) {
+        [attributesStrings addObject:@"readonly"];
+    } else {
+        [attributesStrings addObject:@"readwrite"];
+    }
+
+    // Custom getter/setter
+    SEL customGetter = attributes.customGetter;
+    SEL customSetter = attributes.customSetter;
+    if (customGetter) {
+        [attributesStrings addObject:[NSString stringWithFormat:@"getter=%s", sel_getName(customGetter)]];
+    }
+    if (customSetter) {
+        [attributesStrings addObject:[NSString stringWithFormat:@"setter=%s", sel_getName(customSetter)]];
+    }
+
+    NSString *attributesString = [attributesStrings componentsJoinedByString:@", "];
+    return [NSString stringWithFormat:@"@property (%@) %@", attributesString, self.description];
+}
+
 - (id)getValue:(id)target {
-    return [FLEXRuntimeUtility valueForProperty:self.objc_property onObject:target];
+    // Try custom getter first, then property name
+    SEL customGetter = self.attributes.customGetter;
+    if (customGetter && [target respondsToSelector:customGetter]) {
+        return [target valueForKey:NSStringFromSelector(customGetter)];
+    } else if ([target respondsToSelector:NSSelectorFromString(self.name)]) {
+        return [target valueForKey:self.name];
+    }
+
+    return nil;
 }
 
 - (id)getPotentiallyUnboxedValue:(id)target {

+ 5 - 14
Classes/Utility/Runtime/FLEXRuntimeUtility.h

@@ -95,27 +95,18 @@ typedef NS_ENUM(char, FLEXTypeEncoding)
 /// from the current class to the root-most class.
 + (NSArray<Class> *)classHierarchyOfObject:(id)objectOrClass;
 
-// Property Helpers
-+ (NSString *)prettyNameForProperty:(objc_property_t)property;
-+ (NSString *)typeEncodingForProperty:(objc_property_t)property;
-+ (BOOL)isReadonlyProperty:(objc_property_t)property;
-+ (SEL)setterSelectorForProperty:(objc_property_t)property;
-+ (NSString *)fullDescriptionForProperty:(objc_property_t)property;
-+ (id)valueForProperty:(objc_property_t)property onObject:(id)object;
+/// Used to describe an object in brief within an explorer row
 + (NSString *)summaryForObject:(id)value;
++ (NSString *)safeDescriptionForObject:(id)object;
++ (NSString *)safeDebugDescriptionForObject:(id)object;
+
+// Property Helpers
 + (void)tryAddPropertyWithName:(const char *)name
                     attributes:(NSDictionary<NSString *, NSString *> *)attributePairs
                        toClass:(__unsafe_unretained Class)theClass;
 
-// Ivar Helpers
-+ (NSString *)prettyNameForIvar:(Ivar)ivar;
-+ (id)valueForIvar:(Ivar)ivar onObject:(id)object;
-+ (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object;
-
 // Method Helpers
-+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod;
 + (NSArray *)prettyArgumentComponentsForMethod:(Method)method;
-+ (FLEXTypeEncoding *)returnTypeForMethod:(Method)method;
 
 // Method Calling/Field Editing
 + (id)performSelector:(SEL)selector

+ 3 - 195
Classes/Utility/Runtime/FLEXRuntimeUtility.m

@@ -154,111 +154,6 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     return description;
 }
 
-#pragma mark - Property Helpers (Public)
-
-+ (NSString *)prettyNameForProperty:(objc_property_t)property
-{
-    NSString *name = @(property_getName(property));
-    NSString *encoding = [self typeEncodingForProperty:property];
-    NSString *readableType = [self readableTypeForEncoding:encoding];
-    return [self appendName:name toType:readableType];
-}
-
-+ (NSString *)typeEncodingForProperty:(objc_property_t)property
-{
-    NSDictionary<NSString *, NSString *> *attributesDictionary = [self attributesForProperty:property];
-    return attributesDictionary[kFLEXPropertyAttributeKeyTypeEncoding];
-}
-
-+ (BOOL)isReadonlyProperty:(objc_property_t)property
-{
-    return [self attributesForProperty:property][kFLEXPropertyAttributeKeyReadOnly] != nil;
-}
-
-+ (SEL)setterSelectorForProperty:(objc_property_t)property
-{
-    SEL setterSelector = NULL;
-    NSString *setterSelectorString = [self attributesForProperty:property][kFLEXPropertyAttributeKeyCustomSetter];
-    if (!setterSelectorString) {
-        NSString *propertyName = @(property_getName(property));
-        setterSelectorString = [NSString
-            stringWithFormat:@"set%@%@:",
-            [propertyName substringToIndex:1].uppercaseString,
-            [propertyName substringFromIndex:1]
-        ];
-    }
-    if (setterSelectorString) {
-        setterSelector = NSSelectorFromString(setterSelectorString);
-    }
-    return setterSelector;
-}
-
-+ (NSString *)fullDescriptionForProperty:(objc_property_t)property
-{
-    NSDictionary<NSString *, NSString *> *attributesDictionary = [self attributesForProperty:property];
-    NSMutableArray<NSString *> *attributesStrings = [NSMutableArray array];
-
-    // Atomicity
-    if (attributesDictionary[kFLEXPropertyAttributeKeyNonAtomic]) {
-        [attributesStrings addObject:@"nonatomic"];
-    } else {
-        [attributesStrings addObject:@"atomic"];
-    }
-
-    // Storage
-    if (attributesDictionary[kFLEXPropertyAttributeKeyRetain]) {
-        [attributesStrings addObject:@"strong"];
-    } else if (attributesDictionary[kFLEXPropertyAttributeKeyCopy]) {
-        [attributesStrings addObject:@"copy"];
-    } else if (attributesDictionary[kFLEXPropertyAttributeKeyWeak]) {
-        [attributesStrings addObject:@"weak"];
-    } else {
-        [attributesStrings addObject:@"assign"];
-    }
-
-    // Mutability
-    if (attributesDictionary[kFLEXPropertyAttributeKeyReadOnly]) {
-        [attributesStrings addObject:@"readonly"];
-    } else {
-        [attributesStrings addObject:@"readwrite"];
-    }
-
-    // Custom getter/setter
-    NSString *customGetter = attributesDictionary[kFLEXPropertyAttributeKeyCustomGetter];
-    NSString *customSetter = attributesDictionary[kFLEXPropertyAttributeKeyCustomSetter];
-    if (customGetter) {
-        [attributesStrings addObject:[NSString stringWithFormat:@"getter=%@", customGetter]];
-    }
-    if (customSetter) {
-        [attributesStrings addObject:[NSString stringWithFormat:@"setter=%@", customSetter]];
-    }
-
-    NSString *attributesString = [attributesStrings componentsJoinedByString:@", "];
-    NSString *shortName = [self prettyNameForProperty:property];
-
-    return [NSString stringWithFormat:@"@property (%@) %@", attributesString, shortName];
-}
-
-+ (id)valueForProperty:(objc_property_t)property onObject:(id)object
-{
-    NSString *customGetterString = nil;
-    char *customGetterName = property_copyAttributeValue(property, kFLEXPropertyAttributeKeyCustomGetter.UTF8String);
-    if (customGetterName) {
-        customGetterString = @(customGetterName);
-        free(customGetterName);
-    }
-
-    SEL getterSelector;
-    if (customGetterString.length > 0) {
-        getterSelector = NSSelectorFromString(customGetterString);
-    } else {
-        NSString *propertyName = @(property_getName(property));
-        getterSelector = NSSelectorFromString(propertyName);
-    }
-
-    return [self performSelector:getterSelector onObject:object withArguments:nil error:NULL];
-}
-
 + (NSString *)summaryForObject:(id)value
 {
     NSString *description = nil;
@@ -292,6 +187,9 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     return description;
 }
 
+
+#pragma mark - Property Helpers (Public)
+
 + (void)tryAddPropertyWithName:(const char *)name
                     attributes:(NSDictionary<NSString *, NSString *> *)attributePairs
                        toClass:(__unsafe_unretained Class)theClass
@@ -315,82 +213,8 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     }
 }
 
-
-#pragma mark - Ivar Helpers (Public)
-
-+ (id)valueForIvar:(Ivar)ivar onObject:(id)object
 {
-    id value = nil;
-    const char *type = ivar_getTypeEncoding(ivar);
-#ifdef __arm64__
-    // See http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html
-    const char *name = ivar_getName(ivar);
-    if (type[0] == FLEXTypeEncodingObjcClass && strcmp(name, "isa") == 0) {
-        value = object_getClass(object);
-    } else
-#endif
-    if (type[0] == FLEXTypeEncodingObjcObject || type[0] == FLEXTypeEncodingObjcClass) {
-        value = object_getIvar(object, ivar);
-    } else {
-        ptrdiff_t offset = ivar_getOffset(ivar);
-        void *pointer = (__bridge void *)object + offset;
-        value = [self valueForPrimitivePointer:pointer objCType:type];
-    }
-    return value;
-}
 
-+ (void)setValue:(id)value forIvar:(Ivar)ivar onObject:(id)object
-{
-    const char *typeEncodingCString = ivar_getTypeEncoding(ivar);
-    if (typeEncodingCString[0] == FLEXTypeEncodingObjcObject) {
-        object_setIvar(object, ivar, value);
-    } else if ([value isKindOfClass:[NSValue class]]) {
-        // Primitive - unbox the NSValue.
-        NSValue *valueValue = (NSValue *)value;
-
-        // Make sure that the box contained the correct type.
-        NSAssert(
-            strcmp(valueValue.objCType, typeEncodingCString) == 0,
-            @"Type encoding mismatch (value: %s; ivar: %s) in setting ivar named: %s on object: %@",
-            valueValue.objCType, typeEncodingCString, ivar_getName(ivar), object
-        );
-
-        NSUInteger bufferSize = 0;
-        @try {
-            // NSGetSizeAndAlignment barfs on type encoding for bitfields.
-            NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL);
-        } @catch (NSException *exception) { }
-
-        if (bufferSize > 0) {
-            void *buffer = calloc(bufferSize, 1);
-            [valueValue getValue:buffer];
-            ptrdiff_t offset = ivar_getOffset(ivar);
-            void *pointer = (__bridge void *)object + offset;
-            memcpy(pointer, buffer, bufferSize);
-            free(buffer);
-        }
-    }
-}
-
-
-#pragma mark - Method Helpers (Public)
-
-+ (NSString *)prettyNameForMethod:(Method)method isClassMethod:(BOOL)isClassMethod
-{
-    NSString *selectorName = NSStringFromSelector(method_getName(method));
-    NSString *methodTypeString = isClassMethod ? @"+" : @"-";
-    char *returnType = method_copyReturnType(method);
-    NSString *readableReturnType = [self readableTypeForEncoding:@(returnType)];
-    free(returnType);
-    NSString *prettyName = [NSString stringWithFormat:@"%@ (%@)", methodTypeString, readableReturnType];
-    NSArray<NSString *> *components = [self prettyArgumentComponentsForMethod:method];
-    if (components.count > 0) {
-        prettyName = [prettyName stringByAppendingString:[components componentsJoinedByString:@" "]];
-    } else {
-        prettyName = [prettyName stringByAppendingString:selectorName];
-    }
-
-    return prettyName;
 }
 
 + (NSArray<NSString *> *)prettyArgumentComponentsForMethod:(Method)method
@@ -424,11 +248,6 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     return components;
 }
 
-+ (FLEXTypeEncoding *)returnTypeForMethod:(Method)method
-{
-    return (FLEXTypeEncoding *)method_copyReturnType(method);
-}
-
 
 #pragma mark - Method Calling/Field Editing (Public)
 
@@ -931,17 +750,6 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
 
 #pragma mark - Internal Helpers
 
-+ (NSString *)appendName:(NSString *)name toType:(NSString *)type
-{
-    NSString *combined = nil;
-    if ([type characterAtIndex:type.length - 1] == FLEXTypeEncodingCString) {
-        combined = [type stringByAppendingString:name];
-    } else {
-        combined = [type stringByAppendingFormat:@" %@", name];
-    }
-    return combined;
-}
-
 + (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type
 {
     // Remove the field name if there is any (e.g. \"width\"d -> d)