FLEXProtocol.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //
  2. // FLEXProtocol.m
  3. // FLEX
  4. //
  5. // Derived from MirrorKit.
  6. // Created by Tanner on 6/30/15.
  7. // Copyright (c) 2015 Tanner Bennett. All rights reserved.
  8. //
  9. #import "FLEXProtocol.h"
  10. #import "FLEXProperty.h"
  11. #import <objc/runtime.h>
  12. @implementation FLEXProtocol
  13. - (id)init {
  14. [NSException
  15. raise:NSInternalInconsistencyException
  16. format:@"Class instance should not be created with -init"
  17. ];
  18. return nil;
  19. }
  20. #pragma mark Initializers
  21. + (NSArray *)allProtocols {
  22. unsigned int prcount;
  23. Protocol *__unsafe_unretained*protocols = objc_copyProtocolList(&prcount);
  24. NSMutableArray *all = [NSMutableArray new];
  25. for(NSUInteger i = 0; i < prcount; i++)
  26. [all addObject:[self protocol:protocols[i]]];
  27. free(protocols);
  28. return all;
  29. }
  30. + (instancetype)protocol:(Protocol *)protocol {
  31. return [[self alloc] initWithProtocol:protocol];
  32. }
  33. - (id)initWithProtocol:(Protocol *)protocol {
  34. NSParameterAssert(protocol);
  35. self = [super init];
  36. if (self) {
  37. _objc_protocol = protocol;
  38. [self examine];
  39. }
  40. return self;
  41. }
  42. #pragma mark Other
  43. - (NSString *)description {
  44. return self.name;
  45. }
  46. - (NSString *)debugDescription {
  47. return [NSString stringWithFormat:@"<%@ name=%@, %lu properties, %lu required methods, %lu optional methods, %lu protocols>",
  48. NSStringFromClass(self.class), self.name, (unsigned long)self.properties.count,
  49. (unsigned long)self.requiredMethods.count, (unsigned long)self.optionalMethods.count, (unsigned long)self.protocols.count];
  50. }
  51. - (void)examine {
  52. _name = @(protocol_getName(self.objc_protocol));
  53. unsigned int prcount, pccount, mdrcount, mdocount;
  54. objc_property_t *objcproperties = protocol_copyPropertyList(self.objc_protocol, &prcount);
  55. Protocol * __unsafe_unretained *objcprotocols = protocol_copyProtocolList(self.objc_protocol, &pccount);
  56. struct objc_method_description *objcrmethods = protocol_copyMethodDescriptionList(self.objc_protocol, YES, YES, &mdrcount);
  57. struct objc_method_description *objcomethods = protocol_copyMethodDescriptionList(self.objc_protocol, NO, YES, &mdocount);
  58. NSMutableArray *properties = [NSMutableArray new];
  59. for (int i = 0; i < prcount; i++)
  60. [properties addObject:[FLEXProperty property:objcproperties[i]]];
  61. _properties = properties;
  62. NSMutableArray *protocols = [NSMutableArray new];
  63. for (int i = 0; i < pccount; i++)
  64. [protocols addObject:[FLEXProtocol protocol:objcprotocols[i]]];
  65. _protocols = protocols;
  66. NSMutableArray *requiredMethods = [NSMutableArray new];
  67. for (int i = 0; i < mdrcount; i++)
  68. [requiredMethods addObject:[FLEXMethodDescription description:objcrmethods[i]]];
  69. _requiredMethods = requiredMethods;
  70. NSMutableArray *optionalMethods = [NSMutableArray new];
  71. for (int i = 0; i < mdocount; i++)
  72. [optionalMethods addObject:[FLEXMethodDescription description:objcomethods[i]]];
  73. _optionalMethods = optionalMethods;
  74. free(objcproperties);
  75. free(objcprotocols);
  76. free(objcrmethods);
  77. free(objcomethods);
  78. }
  79. - (BOOL)conformsTo:(Protocol *)protocol {
  80. return protocol_conformsToProtocol(self.objc_protocol, protocol);
  81. }
  82. @end
  83. #pragma mark FLEXMethodDescription
  84. @implementation FLEXMethodDescription
  85. - (id)init {
  86. [NSException
  87. raise:NSInternalInconsistencyException
  88. format:@"Class instance should not be created with -init"
  89. ];
  90. return nil;
  91. }
  92. + (instancetype)description:(struct objc_method_description)methodDescription {
  93. return [[self alloc] initWithDescription:methodDescription];
  94. }
  95. - (id)initWithDescription:(struct objc_method_description)md {
  96. NSParameterAssert(md.name != NULL);
  97. self = [super init];
  98. if (self) {
  99. _objc_description = md;
  100. _selector = md.name;
  101. _typeEncoding = @(md.types);
  102. _returnType = (FLEXTypeEncoding)[self.typeEncoding characterAtIndex:0];
  103. }
  104. return self;
  105. }
  106. - (NSString *)description {
  107. return NSStringFromSelector(self.selector);
  108. }
  109. - (NSString *)debugDescription {
  110. return [NSString stringWithFormat:@"<%@ name=%@, type=%@>",
  111. NSStringFromClass(self.class), NSStringFromSelector(self.selector), self.typeEncoding];
  112. }
  113. @end