FLEXProtocol.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 array];
  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 [NSString stringWithFormat:@"<%@ name=%@, %lu properties, %lu required methods, %lu optional methods, %lu protocols>",
  45. NSStringFromClass(self.class), self.name, (unsigned long)self.properties.count,
  46. (unsigned long)self.requiredMethods.count, (unsigned long)self.optionalMethods.count, (unsigned long)self.protocols.count];
  47. }
  48. - (void)examine {
  49. _name = @(protocol_getName(self.objc_protocol));
  50. unsigned int prcount, pccount, mdrcount, mdocount;
  51. objc_property_t *objcproperties = protocol_copyPropertyList(self.objc_protocol, &prcount);
  52. Protocol * __unsafe_unretained *objcprotocols = protocol_copyProtocolList(self.objc_protocol, &pccount);
  53. struct objc_method_description *objcrmethods = protocol_copyMethodDescriptionList(self.objc_protocol, YES, YES, &mdrcount);
  54. struct objc_method_description *objcomethods = protocol_copyMethodDescriptionList(self.objc_protocol, NO, YES, &mdocount);
  55. NSMutableArray *properties = [NSMutableArray array];
  56. for (int i = 0; i < prcount; i++)
  57. [properties addObject:[FLEXProperty property:objcproperties[i]]];
  58. _properties = properties;
  59. NSMutableArray *protocols = [NSMutableArray array];
  60. for (int i = 0; i < pccount; i++)
  61. [protocols addObject:[FLEXProtocol protocol:objcprotocols[i]]];
  62. _protocols = protocols;
  63. NSMutableArray *requiredMethods = [NSMutableArray array];
  64. for (int i = 0; i < mdrcount; i++)
  65. [requiredMethods addObject:[FLEXMethodDescription description:objcrmethods[i]]];
  66. _requiredMethods = requiredMethods;
  67. NSMutableArray *optionalMethods = [NSMutableArray array];
  68. for (int i = 0; i < mdocount; i++)
  69. [optionalMethods addObject:[FLEXMethodDescription description:objcomethods[i]]];
  70. _optionalMethods = optionalMethods;
  71. free(objcproperties);
  72. free(objcprotocols);
  73. free(objcrmethods);
  74. free(objcomethods);
  75. }
  76. - (BOOL)conformsTo:(Protocol *)protocol {
  77. return protocol_conformsToProtocol(self.objc_protocol, protocol);
  78. }
  79. @end
  80. #pragma mark FLEXMethodDescription
  81. @implementation FLEXMethodDescription
  82. - (id)init {
  83. [NSException
  84. raise:NSInternalInconsistencyException
  85. format:@"Class instance should not be created with -init"
  86. ];
  87. return nil;
  88. }
  89. + (instancetype)description:(struct objc_method_description)methodDescription {
  90. return [[self alloc] initWithDescription:methodDescription];
  91. }
  92. - (id)initWithDescription:(struct objc_method_description)md {
  93. NSParameterAssert(md.name != NULL);
  94. self = [super init];
  95. if (self) {
  96. _objc_description = md;
  97. _selector = md.name;
  98. _typeEncoding = @(md.types);
  99. _returnType = (FLEXTypeEncoding)[self.typeEncoding characterAtIndex:0];
  100. }
  101. return self;
  102. }
  103. - (NSString *)description {
  104. return [NSString stringWithFormat:@"<%@ name=%@, type=%@>",
  105. NSStringFromClass(self.class), NSStringFromSelector(self.selector), self.typeEncoding];
  106. }
  107. @end