Преглед изворни кода

Add list of conformed protocols to object explorer

Tanner Bennett пре 6 година
родитељ
комит
37757d76e1

+ 3 - 1
Classes/ObjectExplorers/FLEXObjectExplorer.h

@@ -10,6 +10,7 @@
 #import "FLEXProperty.h"
 #import "FLEXIvar.h"
 #import "FLEXMethod.h"
+#import "FLEXProtocol.h"
 
 @interface FLEXObjectExplorer : NSObject
 
@@ -46,8 +47,9 @@
 @property (nonatomic, readonly) NSArray<NSArray<FLEXMethod *> *> *allClassMethods;
 @property (nonatomic, readonly) NSArray<FLEXMethod *> *classMethods;
 
+@property (nonatomic, readonly) NSArray<NSArray<FLEXProtocol *> *> *allConformedProtocols;
+@property (nonatomic, readonly) NSArray<FLEXProtocol *> *conformedProtocols;
 @property (nonatomic, readonly) NSArray<Class> *classHierarchy;
-@property (nonatomic, readonly) NSArray<Class> *filteredSuperclasses;
 
 - (void)reloadMetadata;
 - (void)reloadClassHierarchy;

+ 15 - 16
Classes/ObjectExplorers/FLEXObjectExplorer.m

@@ -22,6 +22,7 @@
     NSMutableArray<NSArray<FLEXIvar *> *> *_allIvars;
     NSMutableArray<NSArray<FLEXMethod *> *> *_allMethods;
     NSMutableArray<NSArray<FLEXMethod *> *> *_allClassMethods;
+    NSMutableArray<NSArray<FLEXProtocol *> *> *_allConformedProtocols;
 }
 @end
 
@@ -87,6 +88,7 @@
     _allIvars = [NSMutableArray new];
     _allMethods = [NSMutableArray new];
     _allClassMethods = [NSMutableArray new];
+    _allConformedProtocols = [NSMutableArray new];
 
     [self reloadClassHierarchy];
 
@@ -124,10 +126,17 @@
             superclass:superclass
             kind:FLEXMetadataKindClassMethods
         ]];
+        [_allConformedProtocols addObject:[self
+            metadataUniquedByName:[cls flex_protocols]
+            superclass:superclass
+            kind:FLEXMetadataKindProtocols
+        ]];
     }
 
     // Set up UIKit helper data
-    for (NSArray *matrix in @[_allProperties, _allIvars, _allMethods, _allClassMethods]) {
+    // Really, we only need to call this on properties and ivars
+    // because no other metadata types support editing.
+    for (NSArray *matrix in @[_allProperties, _allIvars, /* _allMethods, _allClassMethods, _allConformedProtocols */]) {
         for (NSArray *metadataByClass in matrix) {
             for (id<FLEXRuntimeMetadata> metadata in metadataByClass) {
                 metadata.tag = metadata.isEditable ? @YES : nil;
@@ -147,6 +156,7 @@
     _ivars = self.allIvars[self.classScope];
     _methods = self.allMethods[self.classScope];
     _classMethods = self.allClassMethods[self.classScope];
+    _conformedProtocols = self.allConformedProtocols[self.classScope];
 }
 
 /// Accepts an array of flex metadata objects and discards objects
@@ -184,6 +194,10 @@
                         return NO;
                     }
                     break;
+
+                case FLEXMetadataKindProtocols:
+                    return YES; // Protocols are already uniqued
+                    break;
                     
                 // Ivars cannot be overidden
                 case FLEXMetadataKindIvars: break;
@@ -203,19 +217,4 @@
     _classHierarchy = [[self.object class] flex_classHierarchy];
 }
 
-//- (void)updateFilteredSuperclasses {
-//    if (self.filterText.length > 0) {
-//        NSMutableArray<Class> *filteredSuperclasses = [NSMutableArray array];
-//        for (Class superclass in self.classHierarchy) {
-//            if ([NSStringFromClass(superclass) localizedCaseInsensitiveContainsString:self.filterText]) {
-//                [filteredSuperclasses addObject:superclass];
-//            }
-//        }
-//        _filteredSuperclasses = filteredSuperclasses;
-//    } else {
-//        _filteredSuperclasses = self.classHierarchy;
-//    }
-//}
-
-
 @end

+ 6 - 5
Classes/ObjectExplorers/FLEXObjectExplorerViewController.m

@@ -32,7 +32,6 @@
 @property (nonatomic) NSArray<FLEXExplorerSection *> *sections;
 @property (nonatomic, readonly) FLEXSingleRowSection *descriptionSection;
 @property (nonatomic, readonly) FLEXExplorerSection *customSection;
-@property (nonatomic, readonly) FLEXSingleRowSection *referencesSection;
 @property (nonatomic) NSIndexSet *customSectionVisibleIndexes;
 
 @end
@@ -133,6 +132,7 @@
     [self reloadData];
 }
 
+
 #pragma mark - Private
 
 - (void)refreshControlDidRefresh:(id)sender
@@ -159,13 +159,13 @@
     }
 
     // Object graph section
-    _referencesSection = [FLEXSingleRowSection
+    FLEXSingleRowSection *referencesSection = [FLEXSingleRowSection
         title:@"Object Graph" reuse:kFLEXDefaultCell cell:^(FLEXTableViewCell *cell) {
-            cell.titleLabel.text = @"Other objects with ivars referencing this object";
+            cell.titleLabel.text = @"See Objects with References to This Object";
             cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
         }
     ];
-    self.referencesSection.selectionAction = ^(UIViewController *host) {
+    referencesSection.selectionAction = ^(UIViewController *host) {
         UIViewController *references = [FLEXInstancesTableViewController
             instancesTableViewControllerForInstancesReferencingObject:explorer.object
         ];
@@ -178,8 +178,9 @@
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindIvars],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindMethods],
         [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassMethods],
-        self.referencesSection
+        [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindProtocols],
 //        [FLEXMetadataSection explorer:self.explorer kind:FLEXMetadataKindClassHierarchy],
+        referencesSection
     ]];
 
     if (self.customSection) {

+ 2 - 1
Classes/ObjectExplorers/Sections/FLEXMetadataSection.h

@@ -14,7 +14,8 @@ typedef NS_ENUM(NSUInteger, FLEXMetadataKind) {
     FLEXMetadataKindClassProperties,
     FLEXMetadataKindIvars,
     FLEXMetadataKindMethods,
-    FLEXMetadataKindClassMethods
+    FLEXMetadataKindClassMethods,
+    FLEXMetadataKindProtocols,
 };
 
 /// This section is used for displaying ObjC runtime metadata

+ 6 - 2
Classes/ObjectExplorers/Sections/FLEXMetadataSection.m

@@ -90,6 +90,8 @@
             return [self titleWithBaseName:@"Methods"];
         case FLEXMetadataKindClassMethods:
             return [self titleWithBaseName:@"Class Methods"];
+        case FLEXMetadataKindProtocols:
+            return [self titleWithBaseName:@"Protocols"];
     }
 }
 
@@ -126,12 +128,14 @@
         case FLEXMetadataKindClassMethods:
             self.allMetadata = self.explorer.classMethods;
             break;
+        case FLEXMetadataKindProtocols:
+            self.allMetadata = self.explorer.conformedProtocols;
     }
 
     // Remove excluded metadata
     if (self.excludedMetadata.count) {
-        id filterBlock = ^BOOL(id obj, NSUInteger idx) {
-            return ![self.excludedMetadata containsObject:[obj name]];
+        id filterBlock = ^BOOL(id<FLEXRuntimeMetadata> obj, NSUInteger idx) {
+            return ![self.excludedMetadata containsObject:obj.name];
         };
 
         // Filter exclusions and sort

+ 1 - 0
Classes/ObjectExplorers/Views/FLEXTableView.m

@@ -100,6 +100,7 @@ FLEXTableViewCellReuseIdentifier const kFLEXCodeFontCell = @"kFLEXCodeFontCell";
     return self;
 }
 
+
 #pragma mark - Public
 
 - (void)registerCells:(NSDictionary<NSString*, Class> *)registrationMapping {

+ 5 - 0
Classes/Utility/Categories/FLEXRuntime+Compare.h

@@ -10,6 +10,7 @@
 #import "FLEXProperty.h"
 #import "FLEXIvar.h"
 #import "FLEXMethodBase.h"
+#import "FLEXProtocol.h"
 
 @interface FLEXProperty (Compare)
 - (NSComparisonResult)compare:(FLEXProperty *)other;
@@ -22,3 +23,7 @@
 @interface FLEXMethodBase (Compare)
 - (NSComparisonResult)compare:(FLEXMethodBase *)other;
 @end
+
+@interface FLEXProtocol (Compare)
+- (NSComparisonResult)compare:(FLEXProtocol *)other;
+@end

+ 8 - 0
Classes/Utility/Categories/FLEXRuntime+Compare.m

@@ -37,3 +37,11 @@
 }
 
 @end
+
+@implementation FLEXProtocol (Compare)
+
+- (NSComparisonResult)compare:(FLEXProtocol *)other {
+    return [self.name caseInsensitiveCompare:other.name];
+}
+
+@end

+ 5 - 1
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.h

@@ -10,8 +10,11 @@
 #import "FLEXProperty.h"
 #import "FLEXIvar.h"
 #import "FLEXMethod.h"
+#import "FLEXProtocol.h"
 
 @protocol FLEXRuntimeMetadata <NSObject>
+
+@property (nonatomic, readonly) NSString *name;
 /// YES for properties and ivars which surely support editing, NO for all methods.
 @property (nonatomic, readonly) BOOL isEditable;
 /// NO for ivars, YES for supported methods and properties
@@ -26,7 +29,7 @@
 - (NSString *)previewWithTarget:(id)object;
 /// For methods, a method calling screen. For all else, an object explorer.
 - (UIViewController *)viewerWithTarget:(id)object;
-/// For methods, nil. For all else, an a field editor screen.
+/// For methods and protocols, nil. For all else, an a field editor screen.
 - (UIViewController *)editorWithTarget:(id)object;
 /// Used to determine present which interactions are possible to the user
 - (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object;
@@ -40,3 +43,4 @@
 @interface FLEXIvar (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXMethodBase (UIKitHelpers) <FLEXRuntimeMetadata> @end
 @interface FLEXMethod (UIKitHelpers) <FLEXRuntimeMetadata> @end
+@interface FLEXProtocol (UIKitHelpers) <FLEXRuntimeMetadata> @end

+ 33 - 0
Classes/Utility/Categories/FLEXRuntime+UIKitHelpers.m

@@ -236,3 +236,36 @@
 }
 
 @end
+
+
+@implementation FLEXProtocol (UIKitHelpers)
+
+- (BOOL)isEditable {
+    return NO;
+}
+
+- (BOOL)isCallable {
+    return NO;
+}
+
+- (id)currentValueWithTarget:(id)object {
+    return nil;
+}
+
+- (NSString *)previewWithTarget:(id)object {
+    return nil;
+}
+
+- (UIViewController *)viewerWithTarget:(id)object {
+    return [FLEXObjectExplorerFactory explorerViewControllerForObject:self];
+}
+
+- (UIViewController *)editorWithTarget:(id)object {
+    return nil;
+}
+
+- (UITableViewCellAccessoryType)suggestedAccessoryTypeWithTarget:(id)object {
+    return UITableViewCellAccessoryDisclosureIndicator;
+}
+
+@end

+ 5 - 2
Classes/Utility/Categories/NSObject+Reflection.h

@@ -9,7 +9,7 @@
 
 #import <Foundation/Foundation.h>
 #import <objc/runtime.h>
-@class FLEXMirror, FLEXMethod, FLEXIvar, FLEXProperty, FLEXMethodBase, FLEXPropertyAttributes;
+@class FLEXMirror, FLEXMethod, FLEXIvar, FLEXProperty, FLEXMethodBase, FLEXPropertyAttributes, FLEXProtocol;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -44,7 +44,10 @@ extern NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger coun
 
 /// @return a list of classes going up the class hierarchy,
 /// starting with the receiver and ending with the root class.
-+ (NSArray<Class> *)flex_classHierarchy;
+@property (nonatomic, readonly, class) NSArray<Class> *flex_classHierarchy;
+
+/// @return a list of protocols this class itself conforms to.
+@property (nonatomic, readonly, class) NSArray<FLEXProtocol *> *flex_protocols;
 
 @end
 

+ 11 - 0
Classes/Utility/Categories/NSObject+Reflection.m

@@ -13,6 +13,7 @@
 #import "FLEXProperty.h"
 #import "FLEXMethod.h"
 #import "FLEXIvar.h"
+#import "FLEXProtocol.h"
 #import "FLEXPropertyAttributes.h"
 #import "NSArray+Functional.h"
 
@@ -130,6 +131,16 @@ NSString * FLEXTypeEncodingString(const char *returnType, NSUInteger count, ...)
     return classes.copy;
 }
 
++ (NSArray<FLEXProtocol *> *)flex_protocols {
+    unsigned int count = 0;
+    Protocol *__unsafe_unretained *list = class_copyProtocolList(self, &count);
+    NSArray<Protocol *> *protocols = [NSArray arrayWithObjects:list count:count];
+    
+    return [protocols flex_mapped:^id(Protocol *pro, NSUInteger idx) {
+        return [FLEXProtocol protocol:pro];
+    }];
+}
+
 @end
 
 

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

@@ -32,6 +32,9 @@
 /// All protocols that this protocol conforms to, if any.
 @property (nonatomic, readonly) NSArray<FLEXProtocol *>  *protocols;
 
+/// For internal use
+@property (nonatomic) id tag;
+
 /// Not to be confused with \c -conformsToProtocol:, which refers to the current
 /// \c FLEXProtocol instance and not the underlying \c Protocol object.
 - (BOOL)conformsTo:(Protocol *)protocol;

+ 8 - 0
Classes/Utility/Runtime/FLEXProtocol.m

@@ -55,6 +55,10 @@
 #pragma mark Other
 
 - (NSString *)description {
+    return self.name;
+}
+
+- (NSString *)debugDescription {
     return [NSString stringWithFormat:@"<%@ name=%@, %lu properties, %lu required methods, %lu optional methods, %lu protocols>",
             NSStringFromClass(self.class), self.name, (unsigned long)self.properties.count,
             (unsigned long)self.requiredMethods.count, (unsigned long)self.optionalMethods.count, (unsigned long)self.protocols.count];
@@ -132,6 +136,10 @@
 }
 
 - (NSString *)description {
+    return NSStringFromSelector(self.selector);
+}
+
+- (NSString *)debugDescription {
     return [NSString stringWithFormat:@"<%@ name=%@, type=%@>",
             NSStringFromClass(self.class), NSStringFromSelector(self.selector), self.typeEncoding];
 }