From 0df7aeddc418946b89f4924efeefbd8d5537fd10 Mon Sep 17 00:00:00 2001 From: Muhammad Hussein Nasrollahpour Date: Sat, 10 May 2014 09:29:35 -0700 Subject: [PATCH 1/3] Add Adopted protocol parsing (for classes, categories and protocols). --- SCKClangSourceFile.m | 141 +++++++++++++++++++++++++++++------- SCKIntrospection.h | 3 + SCKIntrospection.m | 38 +++++++++- TODO | 2 - Tests/ParsingTestFiles/AB.h | 6 +- Tests/TestClangParsing.m | 22 +++++- 6 files changed, 175 insertions(+), 37 deletions(-) diff --git a/SCKClangSourceFile.m b/SCKClangSourceFile.m index f17711d..2796777 100644 --- a/SCKClangSourceFile.m +++ b/SCKClangSourceFile.m @@ -257,6 +257,7 @@ static BOOL isIBOutletFromPropertyOrIvar(CXCursor cursor) - (void) setLocation: (SCKSourceLocation*)aLocation forClass: (NSString*)aClassName withSuperclass: (NSString*)aSuperclassName + adoptedProtocol: (NSString*)adoptedProtocolName isDefinition: (BOOL)isDefinition isForwardDeclaration: (BOOL)isForwardDeclaration { @@ -274,6 +275,14 @@ - (void) setLocation: (SCKSourceLocation*)aLocation [class setSuperclass: [[self collection] classForName: aSuperclassName]]; } + if (nil != adoptedProtocolName) + { + [self addAdoptedProtocolWithName: adoptedProtocolName + toClass: class + toProtocol: nil + toCategory: nil]; + } + if (isDefinition) { [class setDefinition: aLocation]; @@ -286,6 +295,7 @@ - (void) setLocation: (SCKSourceLocation*)aLocation - (void)setLocation: (SCKSourceLocation*)aLocation forCategory: (NSString*)aCategoryName + adoptedProtocol: (NSString*)adoptedProtocolName isDefinition: (BOOL)isDefinition ofClass: (NSString*)aClassName { @@ -301,6 +311,14 @@ - (void)setLocation: (SCKSourceLocation*)aLocation [[class categories] setObject: category forKey: aCategoryName]; } + if (nil != adoptedProtocolName) + { + [self addAdoptedProtocolWithName: adoptedProtocolName + toClass: class + toProtocol: nil + toCategory: category]; + } + if (isDefinition) { [category setDefinition: aLocation]; @@ -490,6 +508,7 @@ - (void)setLocation: (SCKSourceLocation*)sourceLocation - (void) setLocation: (SCKSourceLocation*)sourceLocation forProtocol: (NSString*)protocolName + adoptedProtocol: (NSString*)adoptedProtocolName isForwardDeclaration: (BOOL)isForwardDeclaration { SCKProtocol *protocol = [[self collection] protocolForName: protocolName]; @@ -498,6 +517,15 @@ - (void) setLocation: (SCKSourceLocation*)sourceLocation { return; } + + if (nil != adoptedProtocolName) + { + [self addAdoptedProtocolWithName: adoptedProtocolName + toClass: nil + toProtocol: protocol + toCategory: nil]; + } + [protocol setDeclaration: sourceLocation]; [protocol setDefinition: sourceLocation]; } @@ -631,6 +659,42 @@ - (void)setLocation: (SCKSourceLocation*)sourceLocation } } +- (void)addAdoptedProtocolWithName: (NSString*)adoptedProtocolName + toClass: (SCKClass*)class + toProtocol: (SCKProtocol*)protocol + toCategory: (SCKCategory*)category +{ + SCKProtocol *adoptedProtocol = nil; + + if (nil != class) + { + adoptedProtocol = [[class adoptedProtocols] objectForKey: adoptedProtocolName]; + + if (nil == adoptedProtocol) + { + adoptedProtocol = [[self collection] protocolForName: adoptedProtocolName]; + [[class adoptedProtocols] setObject: adoptedProtocol forKey: adoptedProtocolName]; + } + + if (nil != category) + { + [[category adoptedProtocols] setObject: adoptedProtocol forKey: adoptedProtocolName]; + } + } + + if (nil != protocol) + { + adoptedProtocol = [[protocol adoptedProtocols] objectForKey: adoptedProtocolName]; + + if (nil == adoptedProtocol) + { + adoptedProtocol = [[self collection] protocolForName: adoptedProtocolName]; + [[protocol adoptedProtocols] setObject: adoptedProtocol forKey: adoptedProtocolName]; + } + } +} + + - (void)rebuildIndex { if (0 == translationUnit) { return; } @@ -655,10 +719,15 @@ - (void)rebuildIndex SCOPED_STR(className, clang_getCursorSpelling(cursor)); NSString __block *superclassName = nil; BOOL __block isForwardDeclaration = NO; - + clang_visitChildrenWithBlock(cursor, ^ enum CXChildVisitResult (CXCursor classCursor, CXCursor parent) { + SCOPED_STR(name, clang_getCursorSpelling(classCursor)); + SCOPED_STR(typeEncoding, clang_getDeclObjCTypeEncoding(classCursor)); + SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] + initWithClangSourceLocation: clang_getCursorLocation(classCursor)]; + switch (classCursor.kind) { case CXCursor_ObjCClassRef: @@ -672,13 +741,19 @@ - (void)rebuildIndex superclassName = [NSString stringWithUTF8String: name]; break; } - case CXCursor_ObjCIvarDecl: + case CXCursor_ObjCProtocolRef: { - SCOPED_STR(name, clang_getCursorSpelling(classCursor)); - SCOPED_STR(typeEncoding, clang_getDeclObjCTypeEncoding(classCursor)); - SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] - initWithClangSourceLocation: clang_getCursorLocation(classCursor)]; - + [self setLocation: sourceLocation + forClass: [NSString stringWithUTF8String: className] + withSuperclass: nil + adoptedProtocol: [NSString stringWithUTF8String: name] + isDefinition: NO + isForwardDeclaration: NO]; + + break; + } + case CXCursor_ObjCIvarDecl: + { [self setLocation: sourceLocation forIvar: [NSString stringWithUTF8String: name] withTypeEncoding: [NSString stringWithUTF8String: typeEncoding] @@ -688,10 +763,6 @@ - (void)rebuildIndex } case CXCursor_ObjCPropertyDecl: { - SCOPED_STR(name, clang_getCursorSpelling(classCursor)); - SCOPED_STR(type, clang_getDeclObjCTypeEncoding(classCursor)); - SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] - initWithClangSourceLocation: clang_getCursorLocation(classCursor)]; CXObjCPropertyAttrKind attributes = 0; #if CINDEX_VERSION >= 21 attributes = clang_Cursor_getObjCPropertyAttributes(classCursor, 0); @@ -699,7 +770,7 @@ - (void)rebuildIndex [self setLocation: sourceLocation forProperty: [NSString stringWithUTF8String: name] - withTypeEncoding: [NSString stringWithUTF8String: type] + withTypeEncoding: [NSString stringWithUTF8String: typeEncoding] attributes: attributes isIBOutlet: isIBOutletFromPropertyOrIvar(classCursor) inClass: [NSString stringWithUTF8String: className]]; @@ -707,15 +778,10 @@ - (void)rebuildIndex } case CXCursor_ObjCInstanceMethodDecl: case CXCursor_ObjCClassMethodDecl: - { - SCOPED_STR(name, clang_getCursorSpelling(classCursor)); - SCOPED_STR(type, clang_getDeclObjCTypeEncoding(classCursor)); - SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] - initWithClangSourceLocation: clang_getCursorLocation(classCursor)]; - + { [self setLocation: sourceLocation forMethod: [NSString stringWithUTF8String: name] - withTypeEncoding: [NSString stringWithUTF8String: type] + withTypeEncoding: [NSString stringWithUTF8String: typeEncoding] isClassMethod: (classCursor.kind == CXCursor_ObjCClassMethodDecl) isDefinition: clang_isCursorDefinition(classCursor) inClass: [NSString stringWithUTF8String: className] @@ -735,6 +801,7 @@ - (void)rebuildIndex [self setLocation: classLoc forClass: [NSString stringWithUTF8String: className] withSuperclass: superclassName + adoptedProtocol: nil isDefinition: clang_isCursorDefinition(cursor) isForwardDeclaration: isForwardDeclaration]; break; @@ -748,6 +815,7 @@ - (void)rebuildIndex [self setLocation: classLoc forClass: [NSString stringWithUTF8String: className] withSuperclass: nil + adoptedProtocol: nil isDefinition: clang_isCursorDefinition(cursor) isForwardDeclaration: NO]; @@ -787,22 +855,33 @@ - (void)rebuildIndex [self setLocation: categoryLoc forCategory: [NSString stringWithUTF8String: categoryName] + adoptedProtocol: nil isDefinition: clang_isCursorDefinition(cursor) ofClass: className]; clang_visitChildrenWithBlock(cursor, ^ enum CXChildVisitResult (CXCursor categoryCursor, CXCursor parent) { + SCOPED_STR(name, clang_getCursorSpelling(categoryCursor)); + SCOPED_STR(type, clang_getDeclObjCTypeEncoding(categoryCursor)); + SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] + initWithClangSourceLocation: clang_getCursorLocation(categoryCursor)]; + switch (categoryCursor.kind) { + case CXCursor_ObjCProtocolRef: + { + [self setLocation: sourceLocation + forCategory: [NSString stringWithUTF8String: categoryName] + adoptedProtocol: [NSString stringWithUTF8String: name] + isDefinition: NO + ofClass: className]; + + break; + } case CXCursor_ObjCInstanceMethodDecl: case CXCursor_ObjCClassMethodDecl: { - SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] - initWithClangSourceLocation: clang_getCursorLocation(categoryCursor)]; - SCOPED_STR(name, clang_getCursorSpelling(categoryCursor)); - SCOPED_STR(type, clang_getDeclObjCTypeEncoding(categoryCursor)); - [self setLocation: sourceLocation forMethod: [NSString stringWithUTF8String: name] withTypeEncoding: [NSString stringWithUTF8String: type] @@ -816,10 +895,6 @@ - (void)rebuildIndex case CXCursor_ObjCDynamicDecl: case CXCursor_ObjCPropertyDecl: { - SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] - initWithClangSourceLocation: clang_getCursorLocation(categoryCursor)]; - SCOPED_STR(name, clang_getCursorSpelling(categoryCursor)); - SCOPED_STR(type, clang_getDeclObjCTypeEncoding(categoryCursor)); CXObjCPropertyAttrKind attributes = 0; #if CINDEX_VERSION >= 21 attributes = clang_Cursor_getObjCPropertyAttributes(categoryCursor, 0); @@ -852,6 +927,7 @@ - (void)rebuildIndex // forward declarations as we do with CXCursor_ObjCClassDecl [self setLocation: sourceLocation forProtocol: [NSString stringWithUTF8String: protocolName] + adoptedProtocol: nil isForwardDeclaration: (clang_isCursorDefinition(cursor) == NO)]; clang_visitChildrenWithBlock(cursor, @@ -865,6 +941,15 @@ - (void)rebuildIndex switch (protocolCursor.kind) { + case CXCursor_ObjCProtocolRef: + { + [self setLocation: location + forProtocol: [NSString stringWithUTF8String: protocolName] + adoptedProtocol: [NSString stringWithUTF8String: name] + isForwardDeclaration: NO]; + + break; + } case CXCursor_ObjCPropertyDecl: { CXObjCPropertyAttrKind attributes = 0; diff --git a/SCKIntrospection.h b/SCKIntrospection.h index 6cabb0e..f91c847 100644 --- a/SCKIntrospection.h +++ b/SCKIntrospection.h @@ -66,6 +66,7 @@ @property (nonatomic, readonly, retain) NSMutableArray *subclasses; @property (nonatomic, readonly, retain) NSMutableDictionary *categories; @property (nonatomic, readonly, retain) NSMutableDictionary *methods; +@property (nonatomic, readonly, retain) NSMutableDictionary *adoptedProtocols; @property (nonatomic, readonly, retain) NSMutableArray *ivars; @property (nonatomic, readonly, retain) NSMutableArray *properties; - (SCKIvar*)ivarForName: (NSString *)name; @@ -78,6 +79,7 @@ @property (nonatomic, readonly, retain) NSMutableDictionary *optionalMethods; @property (nonatomic, readonly, retain) NSMutableArray *requiredProperties; @property (nonatomic, readonly, retain) NSMutableArray *optionalProperties; +@property (nonatomic, readonly, retain) NSMutableDictionary *adoptedProtocols; - (SCKProperty*)requiredPropertyForName: (NSString *)aProperty; - (SCKProperty*)optionalPropertyForName: (NSString *)aProperty; @end @@ -85,6 +87,7 @@ @interface SCKCategory : SCKProgramComponent @property (nonatomic, readonly, retain) NSMutableDictionary *methods; @property (nonatomic, readonly, retain) NSMutableArray *properties; +@property (nonatomic, readonly, retain) NSMutableDictionary *adoptedProtocols; - (SCKProperty*)propertyForName: (NSString *)aProperty; @end diff --git a/SCKIntrospection.m b/SCKIntrospection.m index 9246834..f7504a6 100644 --- a/SCKIntrospection.m +++ b/SCKIntrospection.m @@ -42,7 +42,7 @@ - (NSString*)description @end @implementation SCKClass -@synthesize subclasses, superclass, categories, methods, ivars, properties; +@synthesize subclasses, superclass, categories, methods, ivars, properties, adoptedProtocols; - (NSString*)description { NSMutableString *str = [self.name mutableCopy]; @@ -68,6 +68,7 @@ - (id)init methods = [NSMutableDictionary new]; ivars = [NSMutableArray new]; properties = [NSMutableArray new]; + adoptedProtocols = [NSMutableDictionary new]; return self; } - (id)initWithClass: (Class)cls @@ -141,7 +142,7 @@ - (SCKProperty*)propertyForName: (NSString*)name @end @implementation SCKProtocol -@synthesize requiredMethods, optionalMethods, requiredProperties, optionalProperties; +@synthesize requiredMethods, optionalMethods, requiredProperties, optionalProperties, adoptedProtocols; - (id)init { @@ -150,9 +151,35 @@ - (id)init requiredMethods = [NSMutableDictionary new]; optionalProperties = [NSMutableArray new]; requiredProperties = [NSMutableArray new]; + adoptedProtocols [NSMutableDictionary new]; return self; } +- (NSString *)description +{ + NSMutableString *str = [NSMutableString stringWithFormat: @"%@ (%@)", self.parent.name, self.name]; + + for (id optionalMathod in [optionalMethods allValues]) + { + [str appendFormat: @"\n\t%@", optionalMathod]; + } + for (id requiredMethod in [requiredMethods allValues]) + { + [str appendFormat: @"\n\t%@", requiredMethod]; + } + for (id optionalProperty in optionalProperties) + { + [str appendFormat: @"\n\t%@", optionalProperty]; + } + for (id requiredProperty in requiredProperties) + { + [str appendFormat: @"\n\t%@", requiredProperty]; + } + + return str; +} + + - (SCKProperty*)requiredPropertyForName: (NSString*)name { return [[requiredProperties filteredCollectionWithBlock: ^ (SCKProperty *prop) @@ -172,12 +199,13 @@ - (SCKProperty*)optionalPropertyForName: (NSString*)name @end @implementation SCKCategory : SCKProgramComponent -@synthesize methods, properties; +@synthesize methods, properties, adoptedProtocols; - (id)init { SUPERINIT; methods = [NSMutableDictionary new]; properties = [NSMutableArray new]; + adoptedProtocols = [NSMutableDictionary new]; return self; } - (NSString*)description @@ -187,6 +215,10 @@ - (NSString*)description { [str appendFormat: @"\n\t%@", method]; } + for (id property in properties) + { + [str appendFormat: @"\n\t%@", property]; + } return str; } diff --git a/TODO b/TODO index 0842c83..fc94389 100644 --- a/TODO +++ b/TODO @@ -5,8 +5,6 @@ SourceCodeKit TODO - Macro parsing -- Adopted protocol parsing (for classes, categories and protocols) - - Documentation extraction - Capture the method parsing order (for DocGenerator needs) diff --git a/Tests/ParsingTestFiles/AB.h b/Tests/ParsingTestFiles/AB.h index 7d680a3..8127846 100644 --- a/Tests/ParsingTestFiles/AB.h +++ b/Tests/ParsingTestFiles/AB.h @@ -30,11 +30,11 @@ enum enum2 {value4, value5, value6}; @protocol Protocol2; -@protocol Protocol3 +@protocol Protocol3 @end -@interface A : NSObject +@interface A : NSObject { NSString *text; } @@ -47,7 +47,7 @@ enum enum2 {value4, value5, value6}; @end -@interface A (AExtension) +@interface A (AExtension) @property NSString *propertyInsideCategory; diff --git a/Tests/TestClangParsing.m b/Tests/TestClangParsing.m index c5f3d4a..e0a84fa 100644 --- a/Tests/TestClangParsing.m +++ b/Tests/TestClangParsing.m @@ -77,13 +77,19 @@ - (void)testClass { SCKClass *classA = [self parsedClassForName: @"A"]; SCKClass *classB = [self parsedClassForName: @"B"]; + NSMutableDictionary *adoptedProtocols = [classA adoptedProtocols]; + NSSet *adoptedProtocolNames = S(@"Protocol1", @"Protocol3"); SCKFunction *function2 = [[self parsedFunctionsForNames: A(@"function2")] firstObject]; UKNotNil(classA); UKStringsEqual(@"A", [classA name]); UKStringsEqual(@"NSObject", [[classA superclass] name]); UKObjectsEqual([[classB superclass] name], [classA name]); - + + // Adopted protocol related tests + UKObjectsEqual(adoptedProtocolNames, SA([adoptedProtocols allKeys])); + UKObjectsEqual(SA([adoptedProtocols allKeys]), SA((id)[[[adoptedProtocols allValues] mappedCollection] name])); + // FIXME:UKStringsEqual(@"Dummy Class Description", [[class documentation] string]); UKStringsEqual(@"AB.h", [[[classA declaration] file] lastPathComponent]); @@ -100,12 +106,19 @@ - (void)testProtocol SCKProtocol *protocol1 = [self parsedProtocolForName: @"Protocol1"]; SCKProtocol *protocol2 = [self parsedProtocolForName: @"Protocol2"]; SCKProtocol *protocol3 = [self parsedProtocolForName: @"Protocol3"]; + NSMutableDictionary *adoptedProtocols = [protocol3 adoptedProtocols]; + NSSet *adoptedProtocolNames = S(@"Protocol1"); SCKFunction *function2 = [[self parsedFunctionsForNames: A(@"function2")] firstObject]; UKNotNil(protocol1); UKNotNil(protocol2); UKNotNil(protocol3); + // Adopted protocol related tests + UKObjectsEqual(adoptedProtocolNames, SA([adoptedProtocols allKeys])); + UKObjectsEqual(SA([adoptedProtocols allKeys]), SA((id)[[[adoptedProtocols allValues] mappedCollection] name])); + + UKFalse([protocol1 isForwardDeclaration]); UKTrue([protocol2 isForwardDeclaration]); UKFalse([protocol3 isForwardDeclaration]); @@ -195,17 +208,24 @@ - (void)testPropertyInProtocol UKTrue([[date declaration] offset] > [[string declaration] offset]); } + // NOTE: libclang versions prior to 21 parses all protocol properties as required. - (void)testCategory { SCKClass *classA = [self parsedClassForName: @"A"]; SCKClass *classB = [self parsedClassForName: @"B"]; NSMutableDictionary *categories = [classA categories]; + NSMutableDictionary *adoptedProtocols = [[[categories allValues] objectAtIndex: 0] adoptedProtocols]; + NSSet *adoptedProtocolNames = S(@"Protocol1", @"Protocol3"); SCKCategory *aExtension = [categories objectForKey: @"AExtension"]; UKNotNil(aExtension); UKStringsEqual(@"AExtension", [aExtension name]); UKStringsEqual(@"A", [[aExtension parent] name]); + // Adopted protocol related tests + UKObjectsEqual(adoptedProtocolNames, SA([adoptedProtocols allKeys])); + UKObjectsEqual(SA([adoptedProtocols allKeys]), SA((id)[[[adoptedProtocols allValues] mappedCollection] name])); + UKStringsEqual(@"AB.h", [[[aExtension declaration] file] lastPathComponent]); UKTrue([[classA declaration] offset] < [[aExtension declaration] offset]); UKTrue([[classB declaration] offset] > [[aExtension declaration] offset]); From 37ed7a763be42b5a26b78b7e98e9d1345f96d09f Mon Sep 17 00:00:00 2001 From: Muhammad Hussein Nasrollahpour Date: Tue, 20 May 2014 05:30:26 -0700 Subject: [PATCH 2/3] Major cleanup. --- SCKClangSourceFile.m | 102 +++++++++++++++++++----------------- Tests/ParsingTestFiles/AB.h | 16 +++++- Tests/TestClangParsing.m | 8 +-- 3 files changed, 72 insertions(+), 54 deletions(-) diff --git a/SCKClangSourceFile.m b/SCKClangSourceFile.m index 2796777..9345de8 100644 --- a/SCKClangSourceFile.m +++ b/SCKClangSourceFile.m @@ -257,7 +257,7 @@ static BOOL isIBOutletFromPropertyOrIvar(CXCursor cursor) - (void) setLocation: (SCKSourceLocation*)aLocation forClass: (NSString*)aClassName withSuperclass: (NSString*)aSuperclassName - adoptedProtocol: (NSString*)adoptedProtocolName + adoptedProtocols: (NSArray*)adoptedProtocolNames isDefinition: (BOOL)isDefinition isForwardDeclaration: (BOOL)isForwardDeclaration { @@ -275,12 +275,11 @@ - (void) setLocation: (SCKSourceLocation*)aLocation [class setSuperclass: [[self collection] classForName: aSuperclassName]]; } - if (nil != adoptedProtocolName) + if (nil != adoptedProtocolNames) { - [self addAdoptedProtocolWithName: adoptedProtocolName - toClass: class - toProtocol: nil - toCategory: nil]; + [self addAdoptedProtocolWithNames: adoptedProtocolNames + toProgramComponent: class + category: nil]; } if (isDefinition) @@ -295,7 +294,7 @@ - (void) setLocation: (SCKSourceLocation*)aLocation - (void)setLocation: (SCKSourceLocation*)aLocation forCategory: (NSString*)aCategoryName - adoptedProtocol: (NSString*)adoptedProtocolName + adoptedProtocols: (NSArray*)adoptedProtocolNames isDefinition: (BOOL)isDefinition ofClass: (NSString*)aClassName { @@ -311,12 +310,11 @@ - (void)setLocation: (SCKSourceLocation*)aLocation [[class categories] setObject: category forKey: aCategoryName]; } - if (nil != adoptedProtocolName) + if (nil != adoptedProtocolNames) { - [self addAdoptedProtocolWithName: adoptedProtocolName - toClass: class - toProtocol: nil - toCategory: category]; + [self addAdoptedProtocolWithNames: adoptedProtocolNames + toProgramComponent: class + category: category]; } if (isDefinition) @@ -508,7 +506,7 @@ - (void)setLocation: (SCKSourceLocation*)sourceLocation - (void) setLocation: (SCKSourceLocation*)sourceLocation forProtocol: (NSString*)protocolName - adoptedProtocol: (NSString*)adoptedProtocolName + adoptedProtocols: (NSArray*)adoptedProtocolNames isForwardDeclaration: (BOOL)isForwardDeclaration { SCKProtocol *protocol = [[self collection] protocolForName: protocolName]; @@ -518,12 +516,11 @@ - (void) setLocation: (SCKSourceLocation*)sourceLocation return; } - if (nil != adoptedProtocolName) + if (nil != adoptedProtocolNames) { - [self addAdoptedProtocolWithName: adoptedProtocolName - toClass: nil - toProtocol: protocol - toCategory: nil]; + [self addAdoptedProtocolWithNames: adoptedProtocolNames + toProgramComponent: nil + category: nil]; } [protocol setDeclaration: sourceLocation]; @@ -694,6 +691,25 @@ - (void)addAdoptedProtocolWithName: (NSString*)adoptedProtocolName } } +- (void)addAdoptedProtocolWithNames: (NSArray *)adoptedProtocolNames + toProgramComponent: (SCKProgramComponent *)component + category: (SCKCategory *)category +{ + if (nil == adoptedProtocolNames) + { + return; + } + + for (NSString *adoptedProtocolName in adoptedProtocolNames) + { + SCKProtocol *protocol = [[self collection] protocolForName: adoptedProtocolName]; + + [[(id)component adoptedProtocols] setObject: protocol forKey: adoptedProtocolName]; + + [[category adoptedProtocols] setObject: protocol forKey: adoptedProtocolName]; + } +} + - (void)rebuildIndex { @@ -719,6 +735,7 @@ - (void)rebuildIndex SCOPED_STR(className, clang_getCursorSpelling(cursor)); NSString __block *superclassName = nil; BOOL __block isForwardDeclaration = NO; + NSMutableArray __block *adoptedProtocols = [NSMutableArray array]; clang_visitChildrenWithBlock(cursor, ^ enum CXChildVisitResult (CXCursor classCursor, CXCursor parent) @@ -743,12 +760,7 @@ - (void)rebuildIndex } case CXCursor_ObjCProtocolRef: { - [self setLocation: sourceLocation - forClass: [NSString stringWithUTF8String: className] - withSuperclass: nil - adoptedProtocol: [NSString stringWithUTF8String: name] - isDefinition: NO - isForwardDeclaration: NO]; + [adoptedProtocols addObject: [NSString stringWithUTF8String: name]]; break; } @@ -801,7 +813,7 @@ - (void)rebuildIndex [self setLocation: classLoc forClass: [NSString stringWithUTF8String: className] withSuperclass: superclassName - adoptedProtocol: nil + adoptedProtocols: adoptedProtocols isDefinition: clang_isCursorDefinition(cursor) isForwardDeclaration: isForwardDeclaration]; break; @@ -815,7 +827,7 @@ - (void)rebuildIndex [self setLocation: classLoc forClass: [NSString stringWithUTF8String: className] withSuperclass: nil - adoptedProtocol: nil + adoptedProtocols: nil isDefinition: clang_isCursorDefinition(cursor) isForwardDeclaration: NO]; @@ -852,12 +864,7 @@ - (void)rebuildIndex initWithClangSourceLocation: clang_getCursorLocation(cursor)]; SCOPED_STR(categoryName, clang_getCursorSpelling(cursor)); NSString *className = classNameFromCategory(cursor); - - [self setLocation: categoryLoc - forCategory: [NSString stringWithUTF8String: categoryName] - adoptedProtocol: nil - isDefinition: clang_isCursorDefinition(cursor) - ofClass: className]; + NSMutableArray __block *adoptedProtocols = [NSMutableArray array]; clang_visitChildrenWithBlock(cursor, ^ enum CXChildVisitResult (CXCursor categoryCursor, CXCursor parent) @@ -871,11 +878,7 @@ - (void)rebuildIndex { case CXCursor_ObjCProtocolRef: { - [self setLocation: sourceLocation - forCategory: [NSString stringWithUTF8String: categoryName] - adoptedProtocol: [NSString stringWithUTF8String: name] - isDefinition: NO - ofClass: className]; + [adoptedProtocols addObject: [NSString stringWithUTF8String: name]]; break; } @@ -914,6 +917,12 @@ - (void)rebuildIndex } return CXChildVisit_Continue; }); + + [self setLocation: categoryLoc + forCategory: [NSString stringWithUTF8String: categoryName] + adoptedProtocols: adoptedProtocols + isDefinition: clang_isCursorDefinition(cursor) + ofClass: className]; break; } case CXCursor_ObjCProtocolDecl: @@ -922,13 +931,7 @@ - (void)rebuildIndex SCOPED_STR(protocolName, clang_getCursorSpelling(cursor)); SCKSourceLocation *sourceLocation = [[SCKSourceLocation alloc] initWithClangSourceLocation: clang_getCursorLocation(cursor)]; - - // NOTE: We could use CXCursor_ObjCProtocolDecl to parse protocol - // forward declarations as we do with CXCursor_ObjCClassDecl - [self setLocation: sourceLocation - forProtocol: [NSString stringWithUTF8String: protocolName] - adoptedProtocol: nil - isForwardDeclaration: (clang_isCursorDefinition(cursor) == NO)]; + NSMutableArray __block *adoptedProtocols = [NSMutableArray array]; clang_visitChildrenWithBlock(cursor, ^enum CXChildVisitResult(CXCursor protocolCursor, CXCursor parent) @@ -943,10 +946,7 @@ - (void)rebuildIndex { case CXCursor_ObjCProtocolRef: { - [self setLocation: location - forProtocol: [NSString stringWithUTF8String: protocolName] - adoptedProtocol: [NSString stringWithUTF8String: name] - isForwardDeclaration: NO]; + [adoptedProtocols addObject: [NSString stringWithUTF8String: name]]; break; } @@ -992,6 +992,12 @@ - (void)rebuildIndex } return CXChildVisit_Recurse; }); + // NOTE: We could use CXCursor_ObjCProtocolDecl to parse protocol + // forward declarations as we do with CXCursor_ObjCClassDecl + [self setLocation: sourceLocation + forProtocol: [NSString stringWithUTF8String: protocolName] + adoptedProtocols: adoptedProtocols + isForwardDeclaration: (clang_isCursorDefinition(cursor) == NO)]; break; } case CXCursor_FunctionDecl: diff --git a/Tests/ParsingTestFiles/AB.h b/Tests/ParsingTestFiles/AB.h index 8127846..d40d1d0 100644 --- a/Tests/ParsingTestFiles/AB.h +++ b/Tests/ParsingTestFiles/AB.h @@ -33,8 +33,20 @@ enum enum2 {value4, value5, value6}; @protocol Protocol3 @end +@protocol Protocol4 -@interface A : NSObject ++ (void)haveHotChocolate; + +@end + +@protocol Protocol5 + +- (void)haveMilkshake; + +@end + + +@interface A : NSObject { NSString *text; } @@ -47,7 +59,7 @@ enum enum2 {value4, value5, value6}; @end -@interface A (AExtension) +@interface A (AExtension) @property NSString *propertyInsideCategory; diff --git a/Tests/TestClangParsing.m b/Tests/TestClangParsing.m index e0a84fa..1d40320 100644 --- a/Tests/TestClangParsing.m +++ b/Tests/TestClangParsing.m @@ -78,7 +78,7 @@ - (void)testClass SCKClass *classA = [self parsedClassForName: @"A"]; SCKClass *classB = [self parsedClassForName: @"B"]; NSMutableDictionary *adoptedProtocols = [classA adoptedProtocols]; - NSSet *adoptedProtocolNames = S(@"Protocol1", @"Protocol3"); + NSSet *adoptedProtocolNames = S(@"Protocol1", @"Protocol3", @"Protocol4", @"Protocol5"); SCKFunction *function2 = [[self parsedFunctionsForNames: A(@"function2")] firstObject]; UKNotNil(classA); @@ -215,7 +215,7 @@ - (void)testCategory SCKClass *classB = [self parsedClassForName: @"B"]; NSMutableDictionary *categories = [classA categories]; NSMutableDictionary *adoptedProtocols = [[[categories allValues] objectAtIndex: 0] adoptedProtocols]; - NSSet *adoptedProtocolNames = S(@"Protocol1", @"Protocol3"); + NSSet *adoptedProtocolNames = S(@"Protocol4", @"Protocol5"); SCKCategory *aExtension = [categories objectForKey: @"AExtension"]; UKNotNil(aExtension); @@ -242,7 +242,7 @@ - (void)testMethodInCategory SCKCategory *aExtension = [categories objectForKey: @"AExtension"]; NSMutableDictionary *methods = [aExtension methods]; NSSet *methodNames = S(@"propertyInsideCategory", - @"setPropertyInsideCategory:", @"methodInCategory"); + @"setPropertyInsideCategory:", @"methodInCategory", @"haveHotChocolate", @"haveMilkshake"); UKObjectsEqual(methodNames, SA([methods allKeys])); UKObjectsEqual(SA([methods allKeys]), SA((id)[[[methods allValues] mappedCollection] name])); @@ -298,7 +298,7 @@ - (void)testMethod NSMutableDictionary *methods = [classA methods]; NSSet *methodNames = S(@"text", @"setText:", @"wakeUpAtDate:", @"sleepLater:", @"sleepNow", @"propertyInsideCategory", - @"setPropertyInsideCategory:", @"methodInCategory"); + @"setPropertyInsideCategory:", @"methodInCategory", @"haveHotChocolate", @"haveMilkshake"); UKObjectsEqual(methodNames, SA([methods allKeys])); UKObjectsEqual(SA([methods allKeys]), SA((id)[[[methods allValues] mappedCollection] name])); From 20cdb47845c335a0bb3b2780c3252b41e9115399 Mon Sep 17 00:00:00 2001 From: Muhammad Hussein Nasrollahpour Date: Tue, 20 May 2014 05:43:51 -0700 Subject: [PATCH 3/3] Fix missing character. --- SCKIntrospection.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCKIntrospection.m b/SCKIntrospection.m index f7504a6..6831f20 100644 --- a/SCKIntrospection.m +++ b/SCKIntrospection.m @@ -151,7 +151,7 @@ - (id)init requiredMethods = [NSMutableDictionary new]; optionalProperties = [NSMutableArray new]; requiredProperties = [NSMutableArray new]; - adoptedProtocols [NSMutableDictionary new]; + adoptedProtocols = [NSMutableDictionary new]; return self; }