blob: 2fe1575510d039ca9dc533b1c239e612b47024fb [file] [log] [blame]
// -*- mode: ObjC -*-
// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-1998, 2000-2001, 2004-2012 Steve Nygard.
#import "CDOCProtocol.h"
#import "CDClassDump.h"
#import "CDOCMethod.h"
#import "CDVisitor.h"
#import "CDOCProperty.h"
#import "CDMethodType.h"
#import "CDType.h"
#import "CDTypeController.h"
#import "CDVisitorPropertyState.h"
@interface CDOCProtocol ()
@property (nonatomic, readonly) NSString *sortableName;
@end
#pragma mark -
@implementation CDOCProtocol
{
NSString *_name;
NSMutableArray *_protocols;
NSMutableArray *_classMethods;
NSMutableArray *_instanceMethods;
NSMutableArray *_optionalClassMethods;
NSMutableArray *_optionalInstanceMethods;
NSMutableArray *_properties;
NSMutableSet *_adoptedProtocolNames;
}
- (id)init;
{
if ((self = [super init])) {
_name = nil;
_protocols = [[NSMutableArray alloc] init];
_classMethods = [[NSMutableArray alloc] init];
_instanceMethods = [[NSMutableArray alloc] init];
_optionalClassMethods = [[NSMutableArray alloc] init];
_optionalInstanceMethods = [[NSMutableArray alloc] init];
_properties = [[NSMutableArray alloc] init];
_adoptedProtocolNames = [[NSMutableSet alloc] init];
}
return self;
}
#pragma mark - Debugging
- (NSString *)description;
{
return [NSString stringWithFormat:@"<%@:%p> name: %@, protocols: %ld, class methods: %ld, instance methods: %ld",
NSStringFromClass([self class]), self, self.name, [self.protocols count], [self.classMethods count], [self.instanceMethods count]];
}
#pragma mark -
// This assumes that the protocol name doesn't change after it's been added to this.
- (void)addProtocol:(CDOCProtocol *)protocol;
{
if ([_adoptedProtocolNames containsObject:protocol.name] == NO) {
[_protocols addObject:protocol];
[_adoptedProtocolNames addObject:protocol.name];
}
}
- (void)removeProtocol:(CDOCProtocol *)protocol;
{
[_adoptedProtocolNames removeObject:protocol.name];
[_protocols removeObject:protocol];
}
- (NSArray *)protocolNames;
{
NSMutableArray *names = [[NSMutableArray alloc] init];
[self.protocols enumerateObjectsUsingBlock:^(CDOCProtocol *protocol, NSUInteger index, BOOL *stop){
if (protocol.name != nil)
[names addObject:protocol.name];
}];
return [names copy];
}
- (NSString *)protocolsString;
{
NSArray *names = self.protocolNames;
if ([names count] == 0)
return @"";
return [names componentsJoinedByString:@", "];
}
- (void)addClassMethod:(CDOCMethod *)method;
{
[_classMethods addObject:method];
}
- (void)addInstanceMethod:(CDOCMethod *)method;
{
[_instanceMethods addObject:method];
}
- (void)addOptionalClassMethod:(CDOCMethod *)method;
{
[_optionalClassMethods addObject:method];
}
- (void)addOptionalInstanceMethod:(CDOCMethod *)method;
{
[_optionalInstanceMethods addObject:method];
}
- (void)addProperty:(CDOCProperty *)property;
{
[_properties addObject:property];
}
- (BOOL)hasMethods;
{
return [self.classMethods count] > 0 || [self.instanceMethods count] > 0 || [self.optionalClassMethods count] > 0 || [self.optionalInstanceMethods count] > 0;
}
- (void)registerTypesWithObject:(CDTypeController *)typeController phase:(NSUInteger)phase;
{
[self registerTypesFromMethods:self.classMethods withObject:typeController phase:phase];
[self registerTypesFromMethods:self.instanceMethods withObject:typeController phase:phase];
[self registerTypesFromMethods:self.optionalClassMethods withObject:typeController phase:phase];
[self registerTypesFromMethods:self.optionalInstanceMethods withObject:typeController phase:phase];
}
- (void)registerTypesFromMethods:(NSArray *)methods withObject:(CDTypeController *)typeController phase:(NSUInteger)phase;
{
for (CDOCMethod *method in methods) {
for (CDMethodType *methodType in method.parsedMethodTypes) {
[methodType.type phase:phase registerTypesWithObject:typeController usedInMethod:YES];
}
}
}
#pragma mark - Sorting
- (NSString *)sortableName;
{
return self.name;
}
- (NSComparisonResult)ascendingCompareByName:(CDOCProtocol *)otherProtocol;
{
return [self.sortableName compare:otherProtocol.sortableName];
}
#pragma mark -
- (NSString *)methodSearchContext;
{
NSMutableString *resultString = [NSMutableString string];
[resultString appendFormat:@"@protocol %@", self.name];
if ([self.protocols count] > 0)
[resultString appendFormat:@" <%@>", self.protocolsString];
return resultString;
}
- (void)recursivelyVisit:(CDVisitor *)visitor;
{
if ([visitor.classDump shouldShowName:self.name]) {
CDVisitorPropertyState *propertyState = [[CDVisitorPropertyState alloc] initWithProperties:self.properties];
[visitor willVisitProtocol:self];
//[aVisitor willVisitPropertiesOfProtocol:self];
//[self visitProperties:aVisitor];
//[aVisitor didVisitPropertiesOfProtocol:self];
[self visitMethods:visitor propertyState:propertyState];
// @optional properties will generate optional instance methods, and we'll emit @property in the @optional section.
[visitor visitRemainingProperties:propertyState];
[visitor didVisitProtocol:self];
}
}
- (void)visitMethods:(CDVisitor *)visitor propertyState:(CDVisitorPropertyState *)propertyState;
{
NSArray *methods = self.classMethods;
if (visitor.classDump.shouldSortMethods)
methods = [methods sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
for (CDOCMethod *method in methods)
[visitor visitClassMethod:method];
methods = self.instanceMethods;
if (visitor.classDump.shouldSortMethods)
methods = [methods sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
for (CDOCMethod *method in methods)
[visitor visitInstanceMethod:method propertyState:propertyState];
if ([self.optionalClassMethods count] > 0 || [self.optionalInstanceMethods count] > 0) {
[visitor willVisitOptionalMethods];
methods = self.optionalClassMethods;
if (visitor.classDump.shouldSortMethods)
methods = [methods sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
for (CDOCMethod *method in methods)
[visitor visitClassMethod:method];
methods = self.optionalInstanceMethods;
if (visitor.classDump.shouldSortMethods)
methods = [methods sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
for (CDOCMethod *method in methods)
[visitor visitInstanceMethod:method propertyState:propertyState];
[visitor didVisitOptionalMethods];
}
}
#if 0
- (void)visitProperties:(CDVisitor *)visitor;
{
NSArray *array = properties;
if (visitor.classDump.shouldSortMethods)
array = [array sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
for (CDOCProperty *property in array)
[visitor visitProperty:property];
}
#endif
@end