Skip to content

Commit

Permalink
Refactored store registrations API into a NSObject category.
Browse files Browse the repository at this point in the history
This avoids compiler warnings and provides common API definitions for all store registrations.
  • Loading branch information
tomaz committed Apr 11, 2012
1 parent 00fb77a commit acfe7c0
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 80 deletions.
8 changes: 4 additions & 4 deletions AppledocTests/Parsing/ObjectiveCPragmaMarkStateTests.m
Expand Up @@ -29,7 +29,7 @@ - (void)testParseStreamForParserStoreShouldDetectPragmaMarkWithSingleWord {
id store = [OCMockObject mockForClass:[Store class]];
[[store expect] setCurrentSourceInfo:OCMOCK_ANY];
[[store expect] beginMethodGroup];
[[store expect] appendDescription:@"word"];
[[store expect] appendMethodGroupDescription:@"word"];
[[store expect] endCurrentObject];
[[parser expect] popState];
// execute
Expand All @@ -48,7 +48,7 @@ - (void)testParseStreamForParserStoreShouldDetectPragmaMarkWithMultipleWords {
id store = [OCMockObject mockForClass:[Store class]];
[[store expect] setCurrentSourceInfo:OCMOCK_ANY];
[[store expect] beginMethodGroup];
[[store expect] appendDescription:@"word1 word2 word3"];
[[store expect] appendMethodGroupDescription:@"word1 word2 word3"];
[[store expect] endCurrentObject];
[[parser expect] popState];
// execute
Expand All @@ -69,7 +69,7 @@ - (void)testParseStreamForParserStoreShouldDetectPragmaMarkWithMinusPrefix {
id store = [OCMockObject mockForClass:[Store class]];
[[store expect] setCurrentSourceInfo:OCMOCK_ANY];
[[store expect] beginMethodGroup];
[[store expect] appendDescription:@"word1 word2 word3"];
[[store expect] appendMethodGroupDescription:@"word1 word2 word3"];
[[store expect] endCurrentObject];
[[parser expect] popState];
// execute
Expand All @@ -88,7 +88,7 @@ - (void)testParseStreamForParserStoreShouldDetectPragmaMarkWithMinusPrefixAndTak
id store = [OCMockObject mockForClass:[Store class]];
[[store expect] setCurrentSourceInfo:OCMOCK_ANY];
[[store expect] beginMethodGroup];
[[store expect] appendDescription:@"word1 word2 word3 -"];
[[store expect] appendMethodGroupDescription:@"word1 word2 word3 -"];
[[store expect] endCurrentObject];
[[parser expect] popState];
// execute
Expand Down
14 changes: 12 additions & 2 deletions appledoc.xcodeproj/project.pbxproj
Expand Up @@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
73118B12151906F100E9D7F1 /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 73118B11151906F100E9D7F1 /* Constants.m */; };
7316285C15208124002B5FA9 /* ObjectiveCFileStateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7316285B15208124002B5FA9 /* ObjectiveCFileStateTests.m */; };
7316B9D715359DEE000F12F3 /* StoreObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 7316B9D615359DEE000F12F3 /* StoreObject.m */; };
7316B9D815359DEE000F12F3 /* StoreObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 7316B9D615359DEE000F12F3 /* StoreObject.m */; };
7317FAB6150F52D500B39CFD /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7317FAB5150F52D500B39CFD /* SenTestingKit.framework */; };
7317FAB8150F534100B39CFD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7317FAB7150F534100B39CFD /* Cocoa.framework */; };
7317FAC3150F556800B39CFD /* TestCaseBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 7317FAC2150F556800B39CFD /* TestCaseBase.m */; };
Expand Down Expand Up @@ -119,6 +121,9 @@
73118B10151906F100E9D7F1 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
73118B11151906F100E9D7F1 /* Constants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = "<group>"; };
7316285B15208124002B5FA9 /* ObjectiveCFileStateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectiveCFileStateTests.m; sourceTree = "<group>"; };
7316B9D515359DEE000F12F3 /* StoreObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StoreObject.h; sourceTree = "<group>"; };
7316B9D615359DEE000F12F3 /* StoreObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StoreObject.m; sourceTree = "<group>"; };
7316B9DA1535A048000F12F3 /* StoreRegistrations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StoreRegistrations.h; sourceTree = "<group>"; };
7317FA9A150F51FD00B39CFD /* AppledocTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppledocTests.octest; sourceTree = BUILT_PRODUCTS_DIR; };
7317FAB5150F52D500B39CFD /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
7317FAB7150F534100B39CFD /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -332,10 +337,13 @@
73500D2D151748F3000416E3 /* Store */ = {
isa = PBXGroup;
children = (
73500D2E15174910000416E3 /* Store.h */,
73500D2F15174910000416E3 /* Store.m */,
73D540251525A8BA00C57E1B /* StoreConstants.h */,
73D540261525A8BA00C57E1B /* StoreConstants.m */,
7316B9DA1535A048000F12F3 /* StoreRegistrations.h */,
73500D2E15174910000416E3 /* Store.h */,
73500D2F15174910000416E3 /* Store.m */,
7316B9D515359DEE000F12F3 /* StoreObject.h */,
7316B9D615359DEE000F12F3 /* StoreObject.m */,
);
path = Store;
sourceTree = "<group>";
Expand Down Expand Up @@ -601,6 +609,7 @@
73D5402A1525CBB700C57E1B /* ObjectiveCPragmaMarkStateTests.m in Sources */,
73D5402C1525D59600C57E1B /* ObjectiveCEnumStateTests.m in Sources */,
73343BFF15264062006EFF6F /* ObjectiveCStructStateTests.m in Sources */,
7316B9D815359DEE000F12F3 /* StoreObject.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -634,6 +643,7 @@
73F989C81518C6D50068697C /* ObjectiveCStructState.m in Sources */,
73118B12151906F100E9D7F1 /* Constants.m in Sources */,
73D540271525A8BA00C57E1B /* StoreConstants.m in Sources */,
7316B9D715359DEE000F12F3 /* StoreObject.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion appledoc/Parsing/ObjectiveC/ObjectiveCPragmaMarkState.m
Expand Up @@ -60,7 +60,7 @@ - (NSUInteger)parseStream:(TokensStream *)stream forParser:(ObjectiveCParser *)p
LogParVerbose(@"#pragma mark %@", trimmed);
LogParVerbose(@"");
[store beginMethodGroup];
[store appendDescription:trimmed];
[store appendMethodGroupDescription:trimmed];
[store endCurrentObject];
[parser popState];
return GBResultOk;
Expand Down
69 changes: 6 additions & 63 deletions appledoc/Store/Store.h
Expand Up @@ -7,75 +7,18 @@
//

#import "StoreConstants.h"
#import "StoreRegistrations.h"
#import "StoreObject.h"

@class PKToken;

/** The main data store for the application.
The store contains all objects parsed from input files. It's designed as the central object for passing data around various components.
@warning **Implementation detail:** Store is implemented in the way to make registration of various objects as easy as possible. Therefore it let's you build up the objects as data is parsed in. For each object there's corresponding begin method which you need to call prior to registering various data. After all data is collected, you should send `endCurrentObject` to actually register the object with the store. If you detect any incosistency, you should send `cancelCurrentObject` to cancel further registrations. You can nest begin/end/cancel calls, but they need to be balanced: each begin must be followed by an end or cancel! Internally, Store uses a stack on which objects are added when they are started and removed once they are done or cancelled.
@warning **Implementation detail:** Note that Store only handles top-level objects such as classes, categories, protocols, enums etc. If you send any registration message it doesn't recognize, it will try to see if its current object recognizes it and forward the message to it if so. If not, you'll end with unrecognized selector error during runtime.
*/
@interface Store : NSObject
@end

/** Store category declaring API for registering data.
*/
@interface Store (Registrations)

#pragma mark - Classes, categories and protocols

- (void)beginClassWithName:(NSString *)name derivedFromClassWithName:(NSString *)derived;
- (void)beginExtensionForClassWithName:(NSString *)name;
- (void)beginCategoryWithName:(NSString *)category forClassWithName:(NSString *)name;
- (void)beginProtocolWithName:(NSString *)name;
- (void)appendAdoptedProtocolWithName:(NSString *)name;

#pragma mark - Method groups

- (void)beginMethodGroup;
- (void)appendDescription:(NSString *)description;

#pragma mark - Properties

- (void)beginPropertyDefinition;
- (void)beginPropertyAttributes;
- (void)appendPropertyName:(NSString *)name;

#pragma mark - Methods

- (void)beginMethodDefinition;
- (void)appendMethodType:(NSString *)type;
- (void)beginMethodArgument;
- (void)appendMethodArgumentSelector:(NSString *)name;
- (void)appendMethodArgumentVariable:(NSString *)name;

#pragma mark - Enumerations

- (void)beginEnumeration;
- (void)appendEnumerationItem:(NSString *)name;
- (void)appendEnumerationValue:(NSString *)value;

#pragma mark - Structs

- (void)beginStruct;

#pragma mark - Constants

- (void)beginConstant;
- (void)appendConstantType:(NSString *)type;
- (void)appendConstantName:(NSString *)name;

#pragma mark - General objects

- (void)beginTypeDefinition;
- (void)appendType:(NSString *)type;

#pragma mark - Finalizing registrations

- (void)endCurrentObject;
- (void)cancelCurrentObject;

#pragma mark - General information

@property (nonatomic, strong) PKToken *currentSourceInfo;

@end
50 changes: 40 additions & 10 deletions appledoc/Store/Store.m
Expand Up @@ -9,10 +9,47 @@
#import "Objects.h"
#import "Store.h"

@interface Store ()
@property (nonatomic, strong) PKToken *currentSourceInfo;
@property (nonatomic, strong) NSMutableArray *registrationStack;
@property (nonatomic, readonly) id currentRegistrationObject;
@end

#pragma mark -

@implementation Store {
PKToken *_currentSourceInfo;
@implementation Store

@synthesize currentSourceInfo = _currentSourceInfo;
@synthesize currentRegistrationObject = _currentRegistrationObject;
@synthesize registrationStack = _registrationStack;

#pragma mark - Forwarding registrations to objects

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
// Pass selector over to current registration object. If it doesn't recognize it, runtime will fail with "unrecognized selector sent to instance" message. Note that this message is only sent for unrecognized selectors, so we don't have to check our superclass!
return [self.currentRegistrationObject methodSignatureForSelector:selector];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
// If current registration object responds to given method, pass it over, otherwise fail.
if ([self.currentRegistrationObject respondsToSelector:invocation.selector]) {
[invocation invokeWithTarget:self.currentRegistrationObject];
return;
}
[self doesNotRecognizeSelector:invocation.selector];
}

#pragma mark - Properties

- (id)currentRegistrationObject {
return [self.registrationStack lastObject];
}

- (NSMutableArray *)registrationStack {
if (_registrationStack) return _registrationStack;
LogDebug(@"Initializing registration stack due to first access...");
_registrationStack = [[NSMutableArray alloc] init];
return _registrationStack;
}

@end
Expand All @@ -24,8 +61,6 @@ @implementation Store (Registrations)
#pragma mark - Classes, categories and protocols handling

- (void)beginClassWithName:(NSString *)name derivedFromClassWithName:(NSString *)derived {
NSUInteger i=0;
LogParDebug(@"%@ is %d", name, i);
}

- (void)beginExtensionForClassWithName:(NSString *)name {
Expand All @@ -45,7 +80,7 @@ - (void)appendAdoptedProtocolWithName:(NSString *)name {
- (void)beginMethodGroup {
}

- (void)appendDescription:(NSString *)description {
- (void)appendMethodGroupDescription:(NSString *)description {
}

#pragma mark - Properties
Expand Down Expand Up @@ -119,9 +154,4 @@ - (void)endCurrentObject {
- (void)cancelCurrentObject {
}

#pragma mark - General information

- (void)setCurrentSourceInfo:(PKToken *)value { _currentSourceInfo = value; }
- (PKToken *)currentSourceInfo { return _currentSourceInfo; }

@end
19 changes: 19 additions & 0 deletions appledoc/Store/StoreObject.h
@@ -0,0 +1,19 @@
//
// StoreObject.h
// appledoc
//
// Created by Tomaž Kragelj on 4/11/12.
// Copyright (c) 2012 Tomaz Kragelj. All rights reserved.
//

@class PKToken;

/** The base class for all Store objects.
This class serves as a base abstract class that implements common behavior and data storage for all Store objects.
*/
@interface StoreObject : NSObject

@property (nonatomic, strong) PKToken *sourceToken;

@end
15 changes: 15 additions & 0 deletions appledoc/Store/StoreObject.m
@@ -0,0 +1,15 @@
//
// StoreObject.m
// appledoc
//
// Created by Tomaž Kragelj on 4/11/12.
// Copyright (c) 2012 Tomaz Kragelj. All rights reserved.
//

#import "StoreObject.h"

@implementation StoreObject

@synthesize sourceToken;

@end
72 changes: 72 additions & 0 deletions appledoc/Store/StoreRegistrations.h
@@ -0,0 +1,72 @@
//
// StoreRegistrations.h
// appledoc
//
// Created by Tomaž Kragelj on 4/11/12.
// Copyright (c) 2012 Tomaz Kragelj. All rights reserved.
//

/** Store category declaring all API for registering data.
@warning **Note:** We declare this category on NSObject to avoid compiler warnings. Note that not various store objects, including Store itself, only implement a subset of this API. Although Store accepts all these messages, it forwards them to the object that is being registered currently if it doesn't recognize them.
*/
@interface NSObject (StoreRegistrations)

#pragma mark - Classes, categories and protocols

- (void)beginClassWithName:(NSString *)name derivedFromClassWithName:(NSString *)derived;
- (void)beginExtensionForClassWithName:(NSString *)name;
- (void)beginCategoryWithName:(NSString *)category forClassWithName:(NSString *)name;
- (void)beginProtocolWithName:(NSString *)name;
- (void)appendAdoptedProtocolWithName:(NSString *)name;

#pragma mark - Method groups

- (void)beginMethodGroup;
- (void)appendMethodGroupDescription:(NSString *)description;

#pragma mark - Properties

- (void)beginPropertyDefinition;
- (void)beginPropertyAttributes;
- (void)appendPropertyName:(NSString *)name;

#pragma mark - Methods

- (void)beginMethodDefinition;
- (void)appendMethodType:(NSString *)type;
- (void)beginMethodArgument;
- (void)appendMethodArgumentSelector:(NSString *)name;
- (void)appendMethodArgumentVariable:(NSString *)name;

#pragma mark - Enumerations

- (void)beginEnumeration;
- (void)appendEnumerationItem:(NSString *)name;
- (void)appendEnumerationValue:(NSString *)value;

#pragma mark - Structs

- (void)beginStruct;

#pragma mark - Constants

- (void)beginConstant;
- (void)appendConstantType:(NSString *)type;
- (void)appendConstantName:(NSString *)name;

#pragma mark - General objects

- (void)beginTypeDefinition;
- (void)appendType:(NSString *)type;

#pragma mark - Finalizing registrations

- (void)endCurrentObject;
- (void)cancelCurrentObject;

#pragma mark - General information

@property (nonatomic, strong) PKToken *currentSourceInfo;

@end

0 comments on commit acfe7c0

Please sign in to comment.