forked from appsquickly/typhoon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move class creation to their own classes.
A lot of code that used to be in TyphoonFactoryProvider is now in TyphoonAssistedFactoryCreator and its subclasses (one for one factory block, one for a definition block, and one for the future implicit with a result type). The subclasses are supposed to generate a block that returns a TyphoonAssistedFactoryDefinition, which the super class will use in case the class doesn't exists yet (using a block to not instantiate the definition eagerly). TODO: the implicit creation strategy. (appsquickly#102) Conflicts: Pods/Pods.xcodeproj/project.pbxproj
- Loading branch information
1 parent
99f5f47
commit a6c9201
Showing
12 changed files
with
512 additions
and
207 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreator+Private.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreator.h" | ||
|
||
typedef TyphoonAssistedFactoryDefinition *(^TyphoonAssistedFactoryDefinitionProvider)(void); | ||
|
||
@interface TyphoonAssistedFactoryCreator () | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol factoryDefinitionProvider:(TyphoonAssistedFactoryDefinitionProvider)definitionProvider; | ||
|
||
@end |
26 changes: 26 additions & 0 deletions
26
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreator.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
#import "TyphoonAssistedFactoryDefinition.h" | ||
|
||
@interface TyphoonAssistedFactoryCreator : NSObject | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol returns:(Class)returnType; | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol factoryBlock:(id)factoryBlock; | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol factories:(TyphoonAssistedFactoryDefinitionBlock)definitionblock; | ||
|
||
- (Class)factoryClass; | ||
|
||
@end |
202 changes: 202 additions & 0 deletions
202
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreator.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreator.h" | ||
#import "TyphoonAssistedFactoryCreator+Private.h" | ||
|
||
#include <objc/runtime.h> | ||
|
||
#import "TyphoonAssistedFactoryBase.h" | ||
#import "TyphoonAssistedFactoryCreatorImplicit.h" | ||
#import "TyphoonAssistedFactoryCreatorOneFactory.h" | ||
#import "TyphoonAssistedFactoryCreatorManyFactories.h" | ||
#import "TyphoonAssistedFactoryMethodCreator.h" | ||
|
||
@implementation TyphoonAssistedFactoryCreator | ||
{ | ||
@private | ||
Protocol *_protocol; | ||
TyphoonAssistedFactoryDefinitionProvider _definitionProvider; | ||
} | ||
|
||
static dispatch_queue_t sQueue; | ||
|
||
static NSString *GetFactoryClassName(Protocol *protocol) | ||
{ | ||
return [NSString stringWithFormat:@"%s__TyphoonAssistedFactoryImpl", | ||
protocol_getName(protocol)]; | ||
} | ||
|
||
static void AssertValidProtocolForFactory(Protocol *protocol, TyphoonAssistedFactoryDefinition *factoryDefinition) | ||
{ | ||
unsigned int methodCount = 0; | ||
unsigned int propertiesCount = 0; | ||
|
||
struct objc_method_description *methodDescriptions = protocol_copyMethodDescriptionList(protocol, YES, YES, &methodCount); | ||
objc_property_t *properties = protocol_copyPropertyList(protocol, &propertiesCount); | ||
free(methodDescriptions); | ||
free(properties); | ||
|
||
// The readonly properties are returned also as their getter methods, so we | ||
// need to remove those to check that there are only n factory methods left. | ||
NSUInteger factoryMethodCount = [factoryDefinition countOfFactoryMethods]; | ||
NSCAssert(methodCount - propertiesCount == factoryMethodCount, | ||
@"protocol factory method count (%u) differs from factory defintion method count (%lu)", | ||
methodCount - propertiesCount, (unsigned long)factoryMethodCount); | ||
} | ||
|
||
static void AddPropertyGetter(Class factoryClass, objc_property_t property) | ||
{ | ||
// This dummy will give us the type encodings of the properties. | ||
// Only object properties are supported. | ||
Method getter = class_getInstanceMethod([TyphoonAssistedFactoryBase class], @selector(_dummyGetter)); | ||
|
||
const char *cName = property_getName(property); | ||
NSString *name = [NSString stringWithCString:cName encoding:NSASCIIStringEncoding]; | ||
SEL getterSEL = sel_registerName(cName); | ||
|
||
IMP getterIMP = imp_implementationWithBlock(^id (TyphoonAssistedFactoryBase *_self) { | ||
return [_self injectionValueForProperty:name]; | ||
}); | ||
class_addMethod(factoryClass, getterSEL, getterIMP, method_getTypeEncoding(getter)); | ||
} | ||
|
||
static void AddPropertySetter(Class factoryClass, objc_property_t property) | ||
{ | ||
// This dummy will give us the type encodings of the properties. | ||
// Only object properties are supported. | ||
Method setter = class_getInstanceMethod([TyphoonAssistedFactoryBase class], @selector(_setDummySetter:)); | ||
|
||
const char *cName = property_getName(property); | ||
NSString *name = [NSString stringWithCString:cName encoding:NSASCIIStringEncoding]; | ||
NSString *setterName = [NSString stringWithFormat:@"set%@%@:", | ||
[[name substringToIndex:1] uppercaseString], | ||
[name substringFromIndex:1]]; | ||
SEL setterSEL = sel_registerName([setterName cStringUsingEncoding:NSASCIIStringEncoding]); | ||
|
||
IMP setterIMP = imp_implementationWithBlock(^(TyphoonAssistedFactoryBase *_self, id value) { | ||
[_self setInjectionValue:value forProperty:name]; | ||
}); | ||
class_addMethod(factoryClass, setterSEL, setterIMP, method_getTypeEncoding(setter)); | ||
} | ||
|
||
static void AddProperty(Class factoryClass, objc_property_t property) | ||
{ | ||
unsigned int propertyAttributesCount = 0; | ||
const char *cName = property_getName(property); | ||
objc_property_attribute_t *propertyAttributes = property_copyAttributeList(property, &propertyAttributesCount); | ||
class_addProperty(factoryClass, cName, propertyAttributes, propertyAttributesCount); | ||
} | ||
|
||
static void AddPropertiesToFactory(Class factoryClass, Protocol *protocol) | ||
{ | ||
unsigned int propertiesCount = 0; | ||
objc_property_t *properties = protocol_copyPropertyList(protocol, &propertiesCount); | ||
for (unsigned int idx = 0; idx < propertiesCount; idx++) | ||
{ | ||
objc_property_t property = properties[idx]; | ||
AddPropertyGetter(factoryClass, property); | ||
AddPropertySetter(factoryClass, property); | ||
AddProperty(factoryClass, property); | ||
} | ||
free(properties); | ||
} | ||
|
||
static void AddFactoryMethodsToFactory(Class factoryClass, Protocol *protocol, TyphoonAssistedFactoryDefinition *definition) | ||
{ | ||
[definition enumerateFactoryMethods:^(id<TyphoonAssistedFactoryMethod> factoryMethod) { | ||
[[TyphoonAssistedFactoryMethodCreator creatorFor:factoryMethod] | ||
createFromProtocol:protocol inClass:factoryClass]; | ||
}]; | ||
} | ||
|
||
static Class GenerateFactoryClassWithDefinition(Protocol *protocol, TyphoonAssistedFactoryDefinition *factoryDefinition) | ||
{ | ||
NSString *className = GetFactoryClassName(protocol); | ||
const char *cClassName = [className cStringUsingEncoding:NSASCIIStringEncoding]; | ||
|
||
AssertValidProtocolForFactory(protocol, factoryDefinition); | ||
|
||
Class factoryClass = objc_allocateClassPair([TyphoonAssistedFactoryBase class], cClassName, 0); | ||
// Add the factory method first, that way, the setters from the properties | ||
// will not exist yet. | ||
AddFactoryMethodsToFactory(factoryClass, protocol, factoryDefinition); | ||
AddPropertiesToFactory(factoryClass, protocol); | ||
class_addProtocol(factoryClass, protocol); | ||
objc_registerClassPair(factoryClass); | ||
|
||
return factoryClass; | ||
} | ||
|
||
static Class GetExistingFactoryClass(Protocol *protocol) | ||
{ | ||
NSString *className = GetFactoryClassName(protocol); | ||
const char *cClassName = [className cStringUsingEncoding:NSASCIIStringEncoding]; | ||
return objc_getClass(cClassName); | ||
} | ||
|
||
static Class EnsureFactoryClass(Protocol *protocol, TyphoonAssistedFactoryDefinitionProvider definitionProvider) | ||
{ | ||
Class factoryClass = GetExistingFactoryClass(protocol); | ||
if (!factoryClass) | ||
{ | ||
factoryClass = GenerateFactoryClassWithDefinition(protocol, definitionProvider()); | ||
} | ||
|
||
return factoryClass; | ||
} | ||
|
||
+ (void)initialize | ||
{ | ||
if (self == [TyphoonAssistedFactoryCreator class]) | ||
{ | ||
sQueue = dispatch_queue_create("org.typhoonframework.TyphoonAssistedFactoryCreator", DISPATCH_QUEUE_SERIAL); | ||
} | ||
} | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol returns:(Class)returnType | ||
{ | ||
return [[TyphoonAssistedFactoryCreatorImplicit alloc] initWithProtocol:protocol returns:returnType]; | ||
} | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol factoryBlock:(id)factoryBlock | ||
{ | ||
return [[TyphoonAssistedFactoryCreatorOneFactory alloc] initWithProtocol:protocol factoryBlock:factoryBlock]; | ||
} | ||
|
||
+ (instancetype)creatorWithProtocol:(Protocol *)protocol factories:(TyphoonAssistedFactoryDefinitionBlock)definitionblock | ||
{ | ||
return [[TyphoonAssistedFactoryCreatorManyFactories alloc] initWithProtocol:protocol factories:definitionblock]; | ||
} | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol factoryDefinitionProvider:(TyphoonAssistedFactoryDefinitionProvider)definitionProvider | ||
{ | ||
self = [super init]; | ||
if (self) | ||
{ | ||
_protocol = protocol; | ||
_definitionProvider = definitionProvider; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (Class)factoryClass | ||
{ | ||
__block Class factoryClass = nil; | ||
dispatch_sync(sQueue, ^{ | ||
factoryClass = EnsureFactoryClass(_protocol, _definitionProvider); | ||
}); | ||
|
||
return factoryClass; | ||
} | ||
|
||
@end |
18 changes: 18 additions & 0 deletions
18
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreatorImplicit.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreator.h" | ||
|
||
@interface TyphoonAssistedFactoryCreatorImplicit : TyphoonAssistedFactoryCreator | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol returns:(Class)returnType; | ||
|
||
@end |
28 changes: 28 additions & 0 deletions
28
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreatorImplicit.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreatorImplicit.h" | ||
#import "TyphoonAssistedFactoryCreator+Private.h" | ||
|
||
@implementation TyphoonAssistedFactoryCreatorImplicit | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol returns:(Class)returnType | ||
{ | ||
return [super initWithProtocol:protocol factoryDefinitionProvider:^{ | ||
// TODO: guess the mapping | ||
|
||
TyphoonAssistedFactoryDefinition *factoryDefinition = [[TyphoonAssistedFactoryDefinition alloc] init]; | ||
|
||
return factoryDefinition; | ||
}]; | ||
} | ||
|
||
@end |
18 changes: 18 additions & 0 deletions
18
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreatorManyFactories.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreator.h" | ||
|
||
@interface TyphoonAssistedFactoryCreatorManyFactories : TyphoonAssistedFactoryCreator | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol factories:(TyphoonAssistedFactoryDefinitionBlock)definitionBlock; | ||
|
||
@end |
27 changes: 27 additions & 0 deletions
27
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreatorManyFactories.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreatorManyFactories.h" | ||
#import "TyphoonAssistedFactoryCreator+Private.h" | ||
|
||
@implementation TyphoonAssistedFactoryCreatorManyFactories | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol factories:(TyphoonAssistedFactoryDefinitionBlock)definitionBlock | ||
{ | ||
return [super initWithProtocol:protocol factoryDefinitionProvider:^{ | ||
TyphoonAssistedFactoryDefinition *factoryDefinition = [[TyphoonAssistedFactoryDefinition alloc] init]; | ||
[factoryDefinition configure:definitionBlock]; | ||
|
||
return factoryDefinition; | ||
}]; | ||
} | ||
|
||
@end |
18 changes: 18 additions & 0 deletions
18
Source/Component/FactoryProvider/TyphoonAssistedFactoryCreatorOneFactory.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// TYPHOON FRAMEWORK | ||
// Copyright 2013, Jasper Blues & Contributors | ||
// All Rights Reserved. | ||
// | ||
// NOTICE: The authors permit you to use, modify, and distribute this file | ||
// in accordance with the terms of the license agreement accompanying it. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
#import "TyphoonAssistedFactoryCreator.h" | ||
|
||
@interface TyphoonAssistedFactoryCreatorOneFactory : TyphoonAssistedFactoryCreator | ||
|
||
- (instancetype)initWithProtocol:(Protocol *)protocol factoryBlock:(id)factoryBlock; | ||
|
||
@end |
Oops, something went wrong.