diff --git a/README.md b/README.md index 214ce63..f1d0faf 100644 --- a/README.md +++ b/README.md @@ -152,8 +152,7 @@ If you're using the API shoot me an email and tell me what you're doing with it. * Xcode-editor has been tested on Xcode 4+. It should also work on earlier versions of Xcode. * The AppCode IDE from JetBrains is now supported too! -* Uses ARC and weak references so requires OSX 64 bit, and iOS 5. (Non ARC version coming soon.) - +* Supports both ARC and MRR modes of memory management. # Who's using it? diff --git a/Source/Main/Utils/XCKeyBuilder.m b/Source/Main/Utils/XCKeyBuilder.m index c9880da..b420a4c 100755 --- a/Source/Main/Utils/XCKeyBuilder.m +++ b/Source/Main/Utils/XCKeyBuilder.m @@ -10,13 +10,14 @@ //////////////////////////////////////////////////////////////////////////////// #import "XCKeyBuilder.h" +#import "XCMemoryUtils.h" @implementation XCKeyBuilder /* ================================================= Class Methods ================================================== */ + (XCKeyBuilder*) forItemNamed:(NSString*)name { NSData* data = [name dataUsingEncoding:NSUTF8StringEncoding]; - return [[XCKeyBuilder alloc] initHashValueMD5HashWithBytes:[data bytes] length:[data length]]; + return XCAutorelease([[XCKeyBuilder alloc] initHashValueMD5HashWithBytes:[data bytes] length:[data length]]); } diff --git a/Source/Main/Utils/XCMemoryUtils.h b/Source/Main/Utils/XCMemoryUtils.h new file mode 100644 index 0000000..ddb9dcb --- /dev/null +++ b/Source/Main/Utils/XCMemoryUtils.h @@ -0,0 +1,24 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// EXPANZ +// Copyright 2008-2011 EXPANZ +// All Rights Reserved. +// +// NOTICE: Expanz permits you to use, modify, and distribute this file +// in accordance with the terms of the license agreement accompanying it. +// +//////////////////////////////////////////////////////////////////////////////// + +#if !defined(__has_feature) || !__has_feature(objc_arc) + #define XCAutorelease(__var) [__var autorelease]; + #define XCRetain(__var) [__var retain]; + #define XCRetainAutorelease(__var) [[__var retain] autorelease]; + #define XCRelease(__var) [__var release]; + #define XCSuperDealloc [super dealloc]; +#else + #define XCAutorelease(__var) (__var); + #define XCRetain(__var) (__var); + #define XCRetainAutorelease(__var) (__var); + #define XCRelease(__var) (void)(__var); + #define XCSuperDealloc +#endif diff --git a/Source/Main/XCBuildConfigurationList.h b/Source/Main/XCBuildConfigurationList.h new file mode 100644 index 0000000..36a4d1d --- /dev/null +++ b/Source/Main/XCBuildConfigurationList.h @@ -0,0 +1,28 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// EXPANZ +// Copyright 2012 Zach Drayer +// All Rights Reserved. +// +// NOTICE: Zach Drayer permits you to use, modify, and distribute this file +// in accordance with the terms of the license agreement accompanying it. +// +//////////////////////////////////////////////////////////////////////////////// + +@class XCProject; + +@interface XCBuildConfigurationList : NSObject { + @private + NSMutableDictionary *_buildSettings; + NSMutableDictionary *_xcconfigSettings; +} + ++ (NSDictionary *) buildConfigurationsFromDictionary:(NSDictionary *) dictionary inProject:(XCProject *) project; + +@property (nonatomic, readonly) NSDictionary *specifiedBuildSettings; + +- (void) addXCConfigAtPath:(NSString *) path; +- (void) addBuildSettings:(NSDictionary *) buildSettings; + +- (NSString *) valueForKey:(NSString *) key; +@end diff --git a/Source/Main/XCBuildConfigurationList.m b/Source/Main/XCBuildConfigurationList.m new file mode 100644 index 0000000..13ac2c5 --- /dev/null +++ b/Source/Main/XCBuildConfigurationList.m @@ -0,0 +1,146 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// EXPANZ +// Copyright 2012 Zach Drayer +// All Rights Reserved. +// +// NOTICE: Zach Drayer permits you to use, modify, and distribute this file +// in accordance with the terms of the license agreement accompanying it. +// +//////////////////////////////////////////////////////////////////////////////// + +#import "XCBuildConfigurationList.h" +#import "XCGroup.h" +#import "XCProject.h" +#import "XCSourceFile.h" +#import "Utils/XCMemoryUtils.h" + +@implementation XCBuildConfigurationList ++ (NSDictionary *) buildConfigurationsFromDictionary:(NSDictionary *) dictionary inProject:(XCProject *) project { + NSMutableDictionary *configurations = [NSMutableDictionary dictionary]; + + for (NSString* buildConfigurationKey in dictionary) { + NSDictionary* buildConfiguration = [[project objects] objectForKey:buildConfigurationKey]; + + if ([[buildConfiguration valueForKey:@"isa"] asMemberType] == XCBuildConfiguration) { + XCBuildConfigurationList *configuration = [configurations objectForKey:[buildConfiguration objectForKey:@"name"]]; + if (!configuration) { + configuration = [[XCBuildConfigurationList alloc] init]; + + [configurations setObject:configuration forKey:[buildConfiguration objectForKey:@"name"]]; + } + + + XCSourceFile *configurationFile = [project fileWithKey:[buildConfiguration objectForKey:@"baseConfigurationReference"]]; + if (configurationFile) { + NSString *path = configurationFile.path; + + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + XCGroup *group = [project groupWithSourceFile:configurationFile]; + path = [[group pathRelativeToParent] stringByAppendingPathComponent:path]; + } + + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + path = [[[project filePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:path]; + } + + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + path = [[[project filePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:configurationFile.path]; + } + + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + [NSException raise:@"XCConfig not found" format:@"Unable to find XCConfig file at %@", path]; + } + + [configuration addXCConfigAtPath:path]; + } + + [configuration addBuildSettings:[buildConfiguration objectForKey:@"buildSettings"]]; + } + } + + return configurations; +} + +#pragma mark - + +- (id) init { + if (!(self = [super init])) + return nil; + + _buildSettings = [[NSMutableDictionary alloc] init]; + _xcconfigSettings = [[NSMutableDictionary alloc] init]; + + return self; +} + +- (void) dealloc { + XCRelease(_buildSettings) + XCRelease(_xcconfigSettings) + + XCSuperDealloc +} + +#pragma mark - + +- (NSString *) description { + NSMutableString *description = [[super description] mutableCopy]; + + [description appendFormat:@"build settings: %@, inherited: %@", _buildSettings, _xcconfigSettings]; + + return XCAutorelease(description); +} + +#pragma mark - + +- (NSDictionary *) specifiedBuildSettings { + return XCAutorelease([_buildSettings copy]) +} + +#pragma mark - + +- (void) addXCConfigAtPath:(NSString *) path { + path = [[path stringByResolvingSymlinksInPath] stringByExpandingTildeInPath]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + NSString *contents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + + for (NSString *setting in [contents componentsSeparatedByString:@"\n"]) { + // rudimentary #include support + NSString *workingSetting = [setting stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + NSRange range = [workingSetting rangeOfString:@"#include" options:NSAnchoredSearch range:NSMakeRange(0, workingSetting.length)]; + + if (range.location != NSNotFound) { + workingSetting = [workingSetting substringFromIndex:@"#include \"".length]; + + [self addXCConfigAtPath:[setting substringToIndex:(setting.length - 1)]]; + } else { + NSArray *parts = [setting componentsSeparatedByString:@"="]; + if (parts.count == 2) { + // XCConfig files can be used to unset properties, a la `FOO=` + // so, we have to be able to insert blank (but non-nil) values into the dictionary + NSString *key = [[parts objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + NSString *value = [[parts objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + [_xcconfigSettings setObject:value forKey:key]; + } + } + } + } +} + +#pragma mark - + +- (void) addBuildSettings:(NSDictionary *) buildSettings { + [_xcconfigSettings removeObjectsForKeys:[buildSettings allKeys]]; + [_buildSettings addEntriesFromDictionary:buildSettings]; +} + +- (NSString *) valueForKey:(NSString *) key { + NSString *value = [_buildSettings objectForKey:key]; + if (!value) + value = [_xcconfigSettings objectForKey:key]; + return value; +} +@end diff --git a/Source/Main/XCClassDefinition.m b/Source/Main/XCClassDefinition.m index 8c09773..4c30668 100755 --- a/Source/Main/XCClassDefinition.m +++ b/Source/Main/XCClassDefinition.m @@ -10,6 +10,7 @@ //////////////////////////////////////////////////////////////////////////////// #import "XCClassDefinition.h" +#import "Utils/XCMemoryUtils.h" @implementation XCClassDefinition @@ -20,11 +21,11 @@ @implementation XCClassDefinition /* ================================================= Class Methods ================================================== */ + (XCClassDefinition*) classDefinitionWithName:(NSString*)fileName { - return [[XCClassDefinition alloc] initWithName:fileName]; + return XCAutorelease([[XCClassDefinition alloc] initWithName:fileName]) } + (XCClassDefinition*) classDefinitionWithName:(NSString*)className language:(ClassDefinitionLanguage)language { - return [[XCClassDefinition alloc] initWithName:className language:language]; + return XCAutorelease([[XCClassDefinition alloc] initWithName:className language:language]) } @@ -46,6 +47,14 @@ - (id) initWithName:(NSString*)className language:(ClassDefinitionLanguage)langu return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_className) + XCRelease(_header) + XCRelease(_source) + + XCSuperDealloc +} /* ================================================ Interface Methods =============================================== */ - (BOOL) isObjectiveC { diff --git a/Source/Main/XCFileOperationQueue.m b/Source/Main/XCFileOperationQueue.m index 280705b..09a208f 100755 --- a/Source/Main/XCFileOperationQueue.m +++ b/Source/Main/XCFileOperationQueue.m @@ -10,7 +10,7 @@ //////////////////////////////////////////////////////////////////////////////// #import "XCFileOperationQueue.h" -#import "OCLogTemplate.h" +#import "Utils/XCMemoryUtils.h" @interface XCFileOperationQueue () @@ -42,6 +42,16 @@ - (id) initWithBaseDirectory:(NSString*)baseDirectory { return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_baseDirectory) + XCRelease(_filesToWrite) + XCRelease(_frameworksToCopy) + XCRelease(_filesToDelete) + XCRelease(_directoriesToCreate) + + XCSuperDealloc +} /* ================================================ Interface Methods =============================================== */ - (BOOL) fileWithName:(NSString*)name existsInProjectDirectory:(NSString*)directory { NSString* filePath = [self destinationPathFor:name inProjectDirectory:directory]; @@ -69,7 +79,6 @@ - (void) queueFrameworkWithFilePath:(NSString*)filePath inDirectory:(NSString*)d } - (void) queueDeletion:(NSString*)filePath { - LogDebug(@"Queing deletion for path: %@", filePath); [_filesToDelete addObject:filePath]; } @@ -111,7 +120,6 @@ - (void) performCopyFrameworks { } NSError* error = nil; if (![fileManager copyItemAtURL:frameworkPath toURL:destinationUrl error:&error]) { - LogDebug(@"User info: %@", [error userInfo]); [NSException raise:NSInternalInconsistencyException format:@"Error writing file at filePath: %@", [frameworkPath absoluteString]]; } @@ -120,8 +128,6 @@ - (void) performCopyFrameworks { } - (void) performFileDeletions { - LogDebug(@"Files to delete: %@", _filesToDelete); - for (NSString* filePath in [_filesToDelete reverseObjectEnumerator]) { NSString* fullPath = [_baseDirectory stringByAppendingPathComponent:filePath]; NSError* error = nil; diff --git a/Source/Main/XCFrameworkDefinition.m b/Source/Main/XCFrameworkDefinition.m index ee2bdc4..6e55c91 100755 --- a/Source/Main/XCFrameworkDefinition.m +++ b/Source/Main/XCFrameworkDefinition.m @@ -9,7 +9,7 @@ // //////////////////////////////////////////////////////////////////////////////// #import "XCFrameworkDefinition.h" - +#import "Utils/XCMemoryUtils.h" @implementation XCFrameworkDefinition @@ -20,7 +20,7 @@ @implementation XCFrameworkDefinition + (XCFrameworkDefinition*) frameworkDefinitionWithFilePath:(NSString*)filePath copyToDestination:(BOOL)copyToDestination { - return [[XCFrameworkDefinition alloc] initWithFilePath:filePath copyToDestination:copyToDestination]; + return XCAutorelease([[XCFrameworkDefinition alloc] initWithFilePath:filePath copyToDestination:copyToDestination]) } @@ -40,5 +40,10 @@ - (NSString*) name { } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_filePath) + XCSuperDealloc +} @end \ No newline at end of file diff --git a/Source/Main/XCGroup.h b/Source/Main/XCGroup.h index 71bf78a..e315d9c 100755 --- a/Source/Main/XCGroup.h +++ b/Source/Main/XCGroup.h @@ -38,8 +38,8 @@ NSMutableArray* _children; NSMutableArray* _members; - __weak XCFileOperationQueue* _fileOperationQueue; - __weak XCProject* _project; + XCFileOperationQueue* _fileOperationQueue; // weak + XCProject* _project; } diff --git a/Source/Main/XCGroup.m b/Source/Main/XCGroup.m index 33e8273..87a230d 100755 --- a/Source/Main/XCGroup.m +++ b/Source/Main/XCGroup.m @@ -17,11 +17,11 @@ #import "XCGroup.h" #import "XCProject.h" #import "XCClassDefinition.h" -#import "XCKeyBuilder.h" +#import "Utils/XCKeyBuilder.h" +#import "Utils/XCMemoryUtils.h" #import "XCSourceFileDefinition.h" #import "XCSubProjectDefinition.h" #import "XCProject+SubProject.h" -#import "OCLogTemplate.h" /* ================================================================================================================== */ @@ -69,7 +69,7 @@ @implementation XCGroup + (XCGroup*) groupWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)alias path:(NSString*)path children:(NSArray*)children { - return [[XCGroup alloc] initWithProject:project key:key alias:alias path:path children:children]; + return XCAutorelease([[XCGroup alloc] initWithProject:project key:key alias:alias path:path children:children]) } /* ================================================== Initializers ================================================== */ @@ -77,18 +77,29 @@ - (id) initWithProject:(XCProject*)project key:(NSString*)key alias:(NSString*)a children:(NSArray*)children { self = [super init]; if (self) { - _project = project; + _project = XCRetain(project) _fileOperationQueue = [_project fileOperationQueue]; _key = [key copy]; _alias = [alias copy]; _pathRelativeToParent = [path copy]; - - _children = [[NSMutableArray alloc] init]; - [_children addObjectsFromArray:children]; + _children = [children mutableCopy]; } return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_project) + XCRelease(_pathRelativeToParent) + XCRelease(_key) + XCRelease(_alias) + XCRelease(_pathRelativeToProjectRoot) + XCRelease(_children) + XCRelease(_members) + + XCSuperDealloc +} + /* ================================================ Interface Methods =============================================== */ #pragma mark Parent group @@ -98,15 +109,11 @@ - (void) removeFromParentGroup { - (void) removeFromParentGroup:(BOOL)deleteChildren { - LogDebug(@"Removing group %@", [self pathRelativeToProjectRoot]); if (deleteChildren) { - LogDebug(@"Deleting children"); for (id groupMember in [self members]) { if ([groupMember groupMemberType] == PBXGroup) { XCGroup* group = (XCGroup*) groupMember; [group removeFromParentGroup:YES]; - LogDebug(@"My full path is : %@", [group pathRelativeToProjectRoot]); - } else { [_fileOperationQueue queueDeletion:[groupMember pathRelativeToProjectRoot]]; @@ -160,10 +167,8 @@ - (void) addClass:(XCClassDefinition*)classDefinition toTargets:(NSArray*)target - (void) addFramework:(XCFrameworkDefinition*)frameworkDefinition { if (([self memberWithDisplayName:[frameworkDefinition name]]) == nil) { - LogDebug(@"Here we go!!!!"); NSDictionary* fileReference; if ([frameworkDefinition copyToDestination]) { - LogDebug(@"Making file reference"); fileReference = [self makeFileReferenceWithPath:[frameworkDefinition name] name:nil type:Framework]; BOOL copyFramework = NO; if ([frameworkDefinition fileOperationStyle] == FileOperationStyleOverwrite) { @@ -187,7 +192,6 @@ - (void) addFramework:(XCFrameworkDefinition*)frameworkDefinition { NSString* name = [frameworkDefinition name]; fileReference = [self makeFileReferenceWithPath:path name:name type:Framework]; } - LogDebug(@"Make framework key"); NSString* frameworkKey = [[XCKeyBuilder forItemNamed:[frameworkDefinition name]] build]; [[_project objects] setObject:fileReference forKey:frameworkKey]; [self addMemberWithKey:frameworkKey]; @@ -226,7 +230,7 @@ - (XCGroup*) addGroupWithPath:(NSString*)path { NSDictionary* dict = [self asDictionary]; [[_project objects] setObject:dict forKey:_key]; - return group; + return XCAutorelease(group) } - (void) addSourceFile:(XCSourceFileDefinition*)sourceFileDefinition { @@ -355,8 +359,7 @@ - (NSArray*) members { } } } - NSSortDescriptor* sorter = [NSSortDescriptor sortDescriptorWithKey:@"displayName" ascending:YES]; - return [_members sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; + return _members; } - (NSArray*) recursiveMembers { @@ -421,30 +424,33 @@ - (XcodeMemberType) groupMemberType { } - (NSString*) displayName { - if (_pathRelativeToParent == nil) { + if (_alias) return _alias; - } - else { - return [_pathRelativeToParent lastPathComponent]; - } + return [_pathRelativeToParent lastPathComponent]; } - (NSString*) pathRelativeToProjectRoot { if (_pathRelativeToProjectRoot == nil) { NSMutableArray* pathComponents = [[NSMutableArray alloc] init]; - XCGroup* group; - NSString* key = _key; + XCGroup* group = nil; + NSString* key = [_key copy]; while ((group = [_project groupForGroupMemberWithKey:key]) != nil && !([group pathRelativeToParent] == nil)) { [pathComponents addObject:[group pathRelativeToParent]]; - key = [group key]; + id old = key; + key = [[group key] copy]; + XCRelease(old) } NSMutableString* fullPath = [[NSMutableString alloc] init]; for (NSInteger i = (NSInteger)[pathComponents count] - 1; i >= 0; i--) { [fullPath appendFormat:@"%@/", [pathComponents objectAtIndex:i]]; } - _pathRelativeToProjectRoot = [fullPath stringByAppendingPathComponent:_pathRelativeToParent]; + _pathRelativeToProjectRoot = [[fullPath stringByAppendingPathComponent:_pathRelativeToParent] copy]; + + XCRelease(fullPath) + XCRelease(pathComponents) + XCRelease(key) } return _pathRelativeToProjectRoot; } @@ -469,6 +475,7 @@ - (void) addMemberWithKey:(NSString*)key { } - (void) flagMembersAsDirty { + XCRelease(_members) _members = nil; } @@ -493,9 +500,7 @@ - (void) makeGroupMemberWithName:(NSString*)name contents:(id)contents type:(Xco BOOL writeFile = NO; if (fileOperationStyle == FileOperationStyleOverwrite) { writeFile = YES; - if ([_fileOperationQueue fileWithName:name existsInProjectDirectory:filePath]) { - LogInfo(@"*** WARNING *** Group %@ already contains member with name %@. Contents will be updated", [self displayName], name); - } + [_fileOperationQueue fileWithName:name existsInProjectDirectory:filePath]; } else if (fileOperationStyle == FileOperationStyleAcceptExisting && ![_fileOperationQueue fileWithName:name existsInProjectDirectory:filePath]) { @@ -530,8 +535,8 @@ - (void) makeGroupMemberWithName:(NSString*)name path:(NSString*)path type:(Xcod // makes a new group called Products and returns its key - (NSString*) makeProductsGroup:(XCSubProjectDefinition*)xcodeprojDefinition { - NSMutableArray* children = [[NSMutableArray alloc] init]; - NSString* uniquer = [[NSString alloc] init]; + NSMutableArray* children = [NSMutableArray array]; + NSString* uniquer = @""; for (NSString* productName in [xcodeprojDefinition buildProductNames]) { [children addObject:[_project referenceProxyKeyForName:productName]]; uniquer = [uniquer stringByAppendingString:productName]; @@ -551,13 +556,13 @@ - (void) addProductsGroupToProject:(XCSubProjectDefinition*)xcodeprojDefinition NSMutableDictionary* PBXProjectDict = [_project PBXProjectDict]; NSMutableArray* projectReferences = [PBXProjectDict valueForKey:@"projectReferences"]; - NSMutableDictionary* newProjectReference = [[NSMutableDictionary alloc] init]; + NSMutableDictionary* newProjectReference = [NSMutableDictionary dictionary]; [newProjectReference setObject:productKey forKey:@"ProductGroup"]; NSString* projectFileKey = [[_project fileWithName:[xcodeprojDefinition pathRelativeToProjectRoot]] key]; [newProjectReference setObject:projectFileKey forKey:@"ProjectRef"]; if (projectReferences == nil) { - projectReferences = [[NSMutableArray alloc] init]; + projectReferences = [NSMutableArray array]; } [projectReferences addObject:newProjectReference]; [PBXProjectDict setObject:projectReferences forKey:@"projectReferences"]; @@ -629,7 +634,7 @@ - (NSDictionary*) makeFileReferenceWithPath:(NSString*)path name:(NSString*)name - (NSDictionary*) asDictionary { - NSMutableDictionary* groupData = [[NSMutableDictionary alloc] init]; + NSMutableDictionary* groupData = [NSMutableDictionary dictionary]; [groupData setObject:[NSString stringFromMemberType:PBXGroup] forKey:@"isa"]; [groupData setObject:@"" forKey:@"sourceTree"]; @@ -651,7 +656,6 @@ - (XcodeMemberType) typeForKey:(NSString*)key { } - (void) addSourceFile:(XCSourceFile*)sourceFile toTargets:(NSArray*)targets { - LogDebug(@"Adding source file %@ to targets %@", sourceFile, targets); for (XCTarget* target in targets) { [target addMember:sourceFile]; } diff --git a/Source/Main/XCProject+SubProject.m b/Source/Main/XCProject+SubProject.m index 3827fd3..b9e7001 100644 --- a/Source/Main/XCProject+SubProject.m +++ b/Source/Main/XCProject+SubProject.m @@ -11,7 +11,7 @@ #import "XCSourceFile.h" #import "XCTarget.h" -#import "XCKeyBuilder.h" +#import "Utils/XCKeyBuilder.h" #import "XCProject+SubProject.h" #import "XCSubProjectDefinition.h" @@ -52,7 +52,7 @@ - (NSArray*) buildProductsForTargets:(NSString*)xcodeprojKey { NSString* path = (NSString*) [obj valueForKey:@"path"]; if (type != Bundle || [[path pathExtension] isEqualToString:@"bundle"]) { [results addObject:[XCSourceFile sourceFileWithProject:self key:key type:type name:path - sourceTree:nil]]; + sourceTree:nil path:nil]]; } } } @@ -152,7 +152,7 @@ - (NSMutableDictionary*) PBXProjectDict { // returns the key of the PBXContainerItemProxy for the given name and proxy type. nil if not found. - (NSString*) containerItemProxyKeyForName:(NSString*)name proxyType:(NSString*)proxyType { - NSMutableArray* results; + NSMutableArray* results = [[NSMutableArray alloc] init]; [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) { if ([[obj valueForKey:@"isa"] asMemberType] == PBXContainerItemProxy) { NSString* remoteInfo = [obj valueForKey:@"remoteInfo"]; @@ -275,7 +275,7 @@ - (void) addProxies:(XCSubProjectDefinition*)xcodeproj { // remove the PBXContainerItemProxy and PBXReferenceProxy objects for the given object key (which is the PBXFilereference // for the xcodeproj file) - (void) removeProxies:(NSString*)xcodeprojKey { - NSMutableArray* keysToDelete = [[NSMutableArray alloc] init]; + NSMutableArray* keysToDelete = [NSMutableArray array]; // use the xcodeproj's PBXFileReference key to get the PBXContainerItemProxy keys NSArray* containerItemProxyKeys = [self keysForProjectObjectsOfType:PBXContainerItemProxy withIdentifier:xcodeprojKey singleton:NO @@ -313,7 +313,7 @@ - (NSString*) productsGroupKeyForKey:(NSString*)key { - (void) removeFromProjectReferences:(NSString*)key forProductsGroup:(NSString*)productsGroupKey { NSMutableArray* projectReferences = [[self PBXProjectDict] valueForKey:@"projectReferences"]; // remove entry from PBXProject's projectReferences - NSMutableArray* referencesToRemove = [[NSMutableArray alloc] init]; + NSMutableArray* referencesToRemove = [NSMutableArray array]; for (NSDictionary* projectRef in projectReferences) { if ([[projectRef valueForKey:@"ProjectRef"] isEqualToString:key]) { [referencesToRemove addObject:projectRef]; diff --git a/Source/Main/XCProject.h b/Source/Main/XCProject.h index 201c2d4..acb8d71 100755 --- a/Source/Main/XCProject.h +++ b/Source/Main/XCProject.h @@ -19,6 +19,7 @@ @class XCSourceFile; @class XCTarget; @class XCSubProjectDefinition; +@class XCBuildConfigurationList; @interface XCProject : NSObject { @@ -29,6 +30,12 @@ NSString* _filePath; NSMutableDictionary* _dataStore; NSMutableArray* _targets; + + NSMutableDictionary* _groups; + NSMutableDictionary* _configurations; + + NSString* _defaultConfigurationName; + NSString* _rootObjectKey; } @property(nonatomic, strong, readonly) XCFileOperationQueue* fileOperationQueue; @@ -98,6 +105,11 @@ */ - (XCGroup*) rootGroup; +/** + * Returns the root (top-level) groups, if there are multiple. An array of rootGroup if there is only one. + */ +- (NSArray*) rootGroups; + /** * Returns the group with the given key, or nil. */ @@ -113,6 +125,11 @@ */ - (XCGroup*) groupForGroupMemberWithKey:(NSString*)key; +/** + * Returns the parent group for the group or file with the source file + */ +- (XCGroup*) groupWithSourceFile:(XCSourceFile*)sourceFile; + /* ================================================================================================================== */ #pragma mark Targets /** @@ -125,6 +142,15 @@ */ - (XCTarget*) targetWithName:(NSString*)name; +#pragma mark Configurations + +/** +* Returns the target with the specified name, or nil. +*/ +- (NSDictionary*) configurations; +- (NSDictionary*) configurationWithName:(NSString*)name; +- (XCBuildConfigurationList*)defaultConfiguration; + /* ================================================================================================================== */ #pragma mark Saving /** diff --git a/Source/Main/XCProject.m b/Source/Main/XCProject.m index 3679532..4b48b2c 100755 --- a/Source/Main/XCProject.m +++ b/Source/Main/XCProject.m @@ -14,7 +14,8 @@ #import "XCSourceFile.h" #import "XCTarget.h" #import "XCFileOperationQueue.h" -#import "OCLogTemplate.h" +#import "XCBuildConfigurationList.h" +#import "Utils/XCMemoryUtils.h" /* ================================================================================================================== */ @@ -38,16 +39,13 @@ @implementation XCProject /* ================================================= Class Methods ================================================== */ + (XCProject*) projectWithFilePath:(NSString*)filePath { - return [[XCProject alloc] initWithFilePath:filePath]; + return XCAutorelease([[XCProject alloc] initWithFilePath:filePath]) } /* ================================================== Initializers ================================================== */ - (id) initWithFilePath:(NSString*)filePath { - - self = [super init]; - - if (self) { + if ((self = [super init])) { _filePath = [filePath copy]; _dataStore = [[NSMutableDictionary alloc] initWithContentsOfFile:[_filePath stringByAppendingPathComponent:@"project.pbxproj"]]; @@ -55,12 +53,27 @@ - (id) initWithFilePath:(NSString*)filePath { if (!_dataStore) { [NSException raise:NSInvalidArgumentException format:@"Project file not found at file path %@", _filePath]; } + _fileOperationQueue = [[XCFileOperationQueue alloc] initWithBaseDirectory:[_filePath stringByDeletingLastPathComponent]]; + + _groups = [[NSMutableDictionary alloc] init]; } return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_filePath) + XCRelease(_fileOperationQueue) + XCRelease(_dataStore) + XCRelease(_targets) + XCRelease(_groups) + XCRelease(_rootObjectKey) + XCRelease(_defaultConfigurationName) + + XCSuperDealloc +} /* ================================================ Interface Methods =============================================== */ @@ -74,11 +87,10 @@ - (NSArray*) files { NSString* path = [obj valueForKey:@"path"]; NSString* sourceTree = [obj valueForKey:@"sourceTree"]; [results addObject:[XCSourceFile sourceFileWithProject:self key:key type:fileType name:path - sourceTree:(sourceTree ? sourceTree : @"")]]; + sourceTree:(sourceTree ? sourceTree : @"") path:nil]]; } }]; - NSSortDescriptor* sorter = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - return [results sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; + return results; } - (XCSourceFile*) fileWithKey:(NSString*)key { @@ -93,7 +105,7 @@ - (XCSourceFile*) fileWithKey:(NSString*)key { name = [obj valueForKey:@"path"]; } return [XCSourceFile sourceFileWithProject:self key:key type:fileType name:name - sourceTree:(sourceTree ? sourceTree : @"")]; + sourceTree:(sourceTree ? sourceTree : @"") path:[obj valueForKey:@"path"]]; } return nil; } @@ -140,13 +152,13 @@ - (NSString*) filePath { - (NSArray*) groups { NSMutableArray* results = [[NSMutableArray alloc] init]; - [[self objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) { + [[_dataStore objectForKey:@"objects"] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) { if ([[obj valueForKey:@"isa"] asMemberType] == PBXGroup) { [results addObject:[self groupWithKey:key]]; } }]; - return results; + return XCAutorelease(results) } //TODO: Optimize this implementation. @@ -159,16 +171,38 @@ - (XCGroup*) rootGroup { return nil; } +- (NSArray*) rootGroups { + XCGroup *group = [self rootGroup]; + if (group) { + return [NSArray arrayWithObject:group]; + } + + NSMutableArray *results = [NSMutableArray array]; + for (XCGroup* group in [self groups]) { + if ([group parentGroup] == nil) { + [results addObject:group]; + } + } + + return XCAutorelease([results copy]) +} - (XCGroup*) groupWithKey:(NSString*)key { - NSDictionary* obj = [[self objects] valueForKey:key]; + XCGroup *group = [_groups objectForKey:key]; + if (group) + return XCRetainAutorelease(group) + + NSDictionary* obj = [[self objects] objectForKey:key]; if (obj && [[obj valueForKey:@"isa"] asMemberType] == PBXGroup) { NSString* name = [obj valueForKey:@"name"]; NSString* path = [obj valueForKey:@"path"]; NSArray* children = [obj valueForKey:@"children"]; + XCGroup *group = [XCGroup groupWithProject:self key:key alias:name path:path children:children]; + + [_groups setObject:group forKey:key]; - return [XCGroup groupWithProject:self key:key alias:name path:path children:children]; + return group; } return nil; } @@ -176,12 +210,22 @@ - (XCGroup*) groupWithKey:(NSString*)key { - (XCGroup*) groupForGroupMemberWithKey:(NSString*)key { for (XCGroup* group in [self groups]) { if ([group memberWithKey:key]) { - return group; + return XCRetainAutorelease(group) } } return nil; } +- (XCGroup*) groupWithSourceFile:(XCSourceFile*)sourceFile { + for (XCGroup *group in [self groups]) { + for (id member in [group members]) { + if ([member isKindOfClass:[XCSourceFile class]] && [[sourceFile key] isEqualToString:[member key]]) { + return group; + } + } + } + return nil; +} //TODO: This could fail if the path attribute on a given group is more than one directory. Start with candidates and //TODO: search backwards. - (XCGroup*) groupWithPathFromRoot:(NSString*)path { @@ -201,7 +245,7 @@ - (XCGroup*) groupWithPathFromRoot:(NSString*)path { /* ================================================================================================================== */ -#pragma mark Targets +#pragma mark targets - (NSArray*) targets { if (_targets == nil) { @@ -215,8 +259,7 @@ - (NSArray*) targets { } }]; } - NSSortDescriptor* sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - return [_targets sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; + return _targets; } - (XCTarget*) targetWithName:(NSString*)name { @@ -230,9 +273,7 @@ - (XCTarget*) targetWithName:(NSString*)name { - (void) save { [_fileOperationQueue commitFileOperations]; - LogDebug(@"Done committing file operations"); [_dataStore writeToFile:[_filePath stringByAppendingPathComponent:@"project.pbxproj"] atomically:NO]; - LogDebug(@"Done writing project file."); } - (NSMutableDictionary*) objects { @@ -240,9 +281,36 @@ - (NSMutableDictionary*) objects { } +- (NSDictionary*) configurations { + if (_configurations == nil) { + NSString *buildConfigurationRootSectionKey = [[[self objects] objectForKey:[self rootObjectKey]] objectForKey:@"buildConfigurationList"]; + NSDictionary *buildConfigurationDictionary = [[self objects] objectForKey:buildConfigurationRootSectionKey]; + _configurations = [[XCBuildConfigurationList buildConfigurationsFromDictionary:[buildConfigurationDictionary objectForKey:@"buildConfigurations"] inProject:self] mutableCopy]; + _defaultConfigurationName = [[buildConfigurationDictionary objectForKey:@"defaultConfigurationName"] copy]; + } + + return XCAutorelease([_configurations copy]) +} + +- (NSDictionary*) configurationWithName:(NSString*)name { + return [[self configurations] objectForKey:name]; +} + +- (XCBuildConfigurationList*)defaultConfiguration { + return [[self configurations] objectForKey:_defaultConfigurationName]; +} + /* ================================================== Private Methods =============================================== */ #pragma mark Private +- (NSString*) rootObjectKey { + if (_rootObjectKey == nil) { + _rootObjectKey = [[_dataStore objectForKey:@"rootObject"] copy];; + } + + return _rootObjectKey; +} + - (NSArray*) projectFilesOfType:(XcodeSourceFileType)projectFileType { NSMutableArray* results = [NSMutableArray array]; for (XCSourceFile* file in [self files]) { @@ -250,8 +318,7 @@ - (NSArray*) projectFilesOfType:(XcodeSourceFileType)projectFileType { [results addObject:file]; } } - NSSortDescriptor* sorter = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - return [results sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; + return results; } @end \ No newline at end of file diff --git a/Source/Main/XCSourceFile.h b/Source/Main/XCSourceFile.h index 51699ad..fbc3b9e 100755 --- a/Source/Main/XCSourceFile.h +++ b/Source/Main/XCSourceFile.h @@ -20,13 +20,14 @@ @interface XCSourceFile : NSObject { @private - __weak XCProject* _project; + XCProject* _project; NSNumber* _isBuildFile; NSString* _buildFileKey; NSString* _name; NSString* _sourceTree; NSString* _key; + NSString* _path; XcodeSourceFileType _type; } @@ -34,18 +35,21 @@ @property(nonatomic, strong, readonly) NSString* key; @property(nonatomic, strong, readonly) NSString* name; @property(nonatomic, strong, readonly) NSString* sourceTree; +@property(nonatomic, strong, readonly) NSString* path; + (XCSourceFile*) sourceFileWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name - sourceTree:(NSString*)tree; + sourceTree:(NSString*)tree + path:(NSString*)path; - (id) initWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name - sourceTree:(NSString*)tree; + sourceTree:(NSString*)tree + path:(NSString*)path; /** * If yes, indicates the file is able to be included for compilation in an `XCTarget`. diff --git a/Source/Main/XCSourceFile.m b/Source/Main/XCSourceFile.m index efcacec..eddf87a 100755 --- a/Source/Main/XCSourceFile.m +++ b/Source/Main/XCSourceFile.m @@ -11,9 +11,9 @@ #import "XCSourceFile.h" #import "XCProject.h" -#import "XCKeyBuilder.h" +#import "Utils/XCKeyBuilder.h" +#import "Utils/XCMemoryUtils.h" #import "XCGroup.h" -#import "OCLogTemplate.h" @implementation XCSourceFile @@ -21,11 +21,12 @@ @implementation XCSourceFile @synthesize key = _key; @synthesize name = _name; @synthesize sourceTree = _sourceTree; +@synthesize path = _path; /* ================================================= Class Methods ================================================== */ + (XCSourceFile*) sourceFileWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type - name:(NSString*)name sourceTree:(NSString*)_tree { - return [[XCSourceFile alloc] initWithProject:project key:key type:type name:name sourceTree:_tree]; + name:(NSString*)name sourceTree:(NSString*)_tree path:(NSString*)path { + return XCAutorelease([[XCSourceFile alloc] initWithProject:project key:key type:type name:name sourceTree:_tree path:path]) } @@ -34,32 +35,51 @@ - (id) initWithProject:(XCProject*)project key:(NSString*)key type:(XcodeSourceFileType)type name:(NSString*)name - sourceTree:(NSString*)tree { + sourceTree:(NSString*)tree + path:(NSString*)path { self = [super init]; if (self) { - _project = project; + _project = XCRetain(project) _key = [key copy]; _type = type; _name = [name copy]; _sourceTree = [tree copy]; + _path = [path copy]; } return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_project) + XCRelease(_key) + XCRelease(_name) + XCRelease(_sourceTree) + XCRelease(_path) + XCRelease(_buildFileKey) + XCRelease(_isBuildFile) + + XCSuperDealloc +} + /* ================================================ Interface Methods =============================================== */ - (BOOL) isBuildFile { if ([self canBecomeBuildFile] && _isBuildFile == nil) { - _isBuildFile = [NSNumber numberWithBool:NO]; + id old = _isBuildFile; + _isBuildFile = [[NSNumber numberWithBool:NO] copy]; [[_project objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) { if ([[obj valueForKey:@"isa"] asMemberType] == PBXBuildFile) { if ([[obj valueForKey:@"fileRef"] isEqualToString:_key]) { - _isBuildFile = nil; - _isBuildFile = [NSNumber numberWithBool:YES]; + XCRelease(_isBuildFile) + _isBuildFile = nil; + + _isBuildFile = [[NSNumber numberWithBool:YES] copy]; } } }]; + XCRelease(old) } return [_isBuildFile boolValue]; } @@ -93,12 +113,12 @@ - (NSString*) buildFileKey { [[_project objects] enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSDictionary* obj, BOOL* stop) { if ([[obj valueForKey:@"isa"] asMemberType] == PBXBuildFile) { if ([[obj valueForKey:@"fileRef"] isEqualToString:_key]) { - _buildFileKey = key; + _buildFileKey = [key copy]; } } }]; } - return _buildFileKey; + return XCAutorelease([_buildFileKey copy]) } @@ -133,15 +153,15 @@ - (NSString*) displayName { } - (NSString*) pathRelativeToProjectRoot { + if (_path) { + return _path; + } if ([self.sourceTree isEqualToString:@"SOURCE_ROOT"]) { return _name; } - else { - NSString* parentPath = [[_project groupForGroupMemberWithKey:_key] pathRelativeToProjectRoot]; - NSString* result = [parentPath stringByAppendingPathComponent:_name]; - LogDebug(@"%@ -> %@ -> %@", _name, parentPath, result); - return result; - } + NSString* parentPath = [[_project groupForGroupMemberWithKey:_key] pathRelativeToProjectRoot]; + NSString* result = [parentPath stringByAppendingPathComponent:_name]; + return result; } /* ================================================== Utility Methods =============================================== */ diff --git a/Source/Main/XCSourceFileDefinition.m b/Source/Main/XCSourceFileDefinition.m index 79341b5..6ebe660 100644 --- a/Source/Main/XCSourceFileDefinition.m +++ b/Source/Main/XCSourceFileDefinition.m @@ -10,7 +10,7 @@ //////////////////////////////////////////////////////////////////////////////// #import "XCSourceFileDefinition.h" - +#import "Utils/XCMemoryUtils.h" @implementation XCSourceFileDefinition @@ -22,13 +22,13 @@ @implementation XCSourceFileDefinition + (XCSourceFileDefinition*) sourceDefinitionWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileType)type { - return [[XCSourceFileDefinition alloc] initWithName:name text:text type:type]; + return XCAutorelease([[XCSourceFileDefinition alloc] initWithName:name text:text type:type]) } + (XCSourceFileDefinition*) sourceDefinitionWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType)type { - return [[XCSourceFileDefinition alloc] initWithName:name data:data type:type]; + return XCAutorelease([[XCSourceFileDefinition alloc] initWithName:name data:data type:type]) } @@ -37,7 +37,7 @@ - (id) initWithName:(NSString*)name text:(NSString*)text type:(XcodeSourceFileTy self = [super init]; if (self) { _sourceFileName = [name copy]; - _data = [text dataUsingEncoding:NSUTF8StringEncoding]; + _data = [[text dataUsingEncoding:NSUTF8StringEncoding] copy]; _type = type; } return self; @@ -54,4 +54,12 @@ - (id) initWithName:(NSString*)name data:(NSData*)data type:(XcodeSourceFileType } + +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_sourceFileName) + XCRelease(_data) + + XCSuperDealloc +} @end \ No newline at end of file diff --git a/Source/Main/XCSubProjectDefinition.h b/Source/Main/XCSubProjectDefinition.h index 35627e7..e018101 100644 --- a/Source/Main/XCSubProjectDefinition.h +++ b/Source/Main/XCSubProjectDefinition.h @@ -11,7 +11,7 @@ #import #import "XCAbstractDefinition.h" -#import +#import "XcodeSourceFileType.h" @class XCProject; @@ -22,8 +22,10 @@ NSString* _path; XcodeSourceFileType _type; XCProject* _subProject; + XCProject* _parentProject; NSString* _key; NSString* _fullProjectPath; + NSString* _relativePath; } diff --git a/Source/Main/XCSubProjectDefinition.m b/Source/Main/XCSubProjectDefinition.m index 5100c3b..a6eb399 100644 --- a/Source/Main/XCSubProjectDefinition.m +++ b/Source/Main/XCSubProjectDefinition.m @@ -12,6 +12,7 @@ #import "XCProject.h" #import "XCProject+SubProject.h" #import "XCSubProjectDefinition.h" +#import "Utils/XCMemoryUtils.h" @interface XCSubProjectDefinition () @property(nonatomic, strong, readwrite) NSString* relativePath; @@ -32,7 +33,7 @@ @implementation XCSubProjectDefinition + (XCSubProjectDefinition*) withName:(NSString*)name path:(NSString*)path parentProject:(XCProject*)parentProject { - return [[XCSubProjectDefinition alloc] initWithName:name path:path parentProject:parentProject]; + return XCAutorelease([[XCSubProjectDefinition alloc] initWithName:name path:path parentProject:parentProject]) } /* ================================================== Initializers ================================================== */ @@ -45,12 +46,25 @@ - (id) initWithName:(NSString*)name path:(NSString*)path parentProject:(XCProjec _name = [name copy]; _path = [path copy]; _type = XcodeProject; - _parentProject = parentProject; + _parentProject = XCRetain(parentProject) _subProject = [[XCProject alloc] initWithFilePath:[NSString stringWithFormat:@"%@/%@.xcodeproj", path, name]]; } return self; } +- (void) dealloc { + XCRelease(_name) + XCRelease(_name) + XCRelease(_path) + XCRelease(_parentProject) + XCRelease(_subProject) + XCRelease(_relativePath) + XCRelease(_key) + XCRelease(_fullProjectPath) + + XCSuperDealloc +} + /* ================================================ Interface Methods =============================================== */ - (NSString*) projectFileName { return [_name stringByAppendingString:@".xcodeproj"]; @@ -83,18 +97,18 @@ - (NSString*) projectKey { if (_key == nil) { NSArray* xcodeprojKeys = [_parentProject keysForProjectObjectsOfType:PBXFileReference withIdentifier:[self pathRelativeToProjectRoot] singleton:YES required:YES]; - _key = [xcodeprojKeys objectAtIndex:0]; + _key = [[xcodeprojKeys objectAtIndex:0] copy]; } - return _key; + return XCAutorelease([_key copy]) } - (void) initFullProjectPath:(NSString*)fullProjectPath groupPath:(NSString*)groupPath { if (groupPath != nil) { - NSMutableArray* fullPathComponents = [[fullProjectPath pathComponents] mutableCopy]; + NSMutableArray* fullPathComponents = XCAutorelease([[fullProjectPath pathComponents] mutableCopy]) [fullPathComponents removeLastObject]; fullProjectPath = [[NSString pathWithComponents:fullPathComponents] stringByAppendingFormat:@"/%@", groupPath]; } - _fullProjectPath = fullProjectPath; + _fullProjectPath = [fullProjectPath copy]; } @@ -105,9 +119,9 @@ - (NSString*) pathRelativeToProjectRoot { if (_fullProjectPath == nil) { [NSException raise:NSInvalidArgumentException format:@"fullProjectPath has not been set"]; } - NSMutableArray* projectPathComponents = [[_fullProjectPath pathComponents] mutableCopy]; + NSMutableArray* projectPathComponents = XCAutorelease([[_fullProjectPath pathComponents] mutableCopy]); NSArray* objectPathComponents = [[self fullPathName] pathComponents]; - NSString* convertedPath = [[NSString alloc] init]; + NSString* convertedPath = @""; // skip over path components from root that are equal NSInteger limit = ([projectPathComponents count] < [objectPathComponents count]) ? [projectPathComponents count] : @@ -132,13 +146,13 @@ - (NSString*) pathRelativeToProjectRoot { } _relativePath = [[convertedPath stringByAppendingString:[objectPathComponents lastObject]] copy]; } - return _relativePath; + return XCAutorelease([_relativePath copy]); } /* ================================================== Utility Methods =============================================== */ - (NSString*) description { - return [NSString stringWithFormat:@"XcodeprojDefinition: sourceFileName = %@, path=%@, type=%u", _name, _path, _type]; + return [NSString stringWithFormat:@"XcodeprojDefinition: sourceFileName = %@, path=%@, type=%d", _name, _path, _type]; } @end \ No newline at end of file diff --git a/Source/Main/XCTarget.h b/Source/Main/XCTarget.h index 6b60ecc..a451817 100755 --- a/Source/Main/XCTarget.h +++ b/Source/Main/XCTarget.h @@ -13,21 +13,24 @@ @class XCProject; @class XCSourceFile; +@class XCBuildConfigurationList; /** * Represents a target in an xcode project. */ @interface XCTarget : NSObject { - __weak XCProject* _project; + XCProject* _project; NSString* _key; NSString* _name; NSString* _productName; NSString* _productReference; + NSString* _defaultConfigurationName; @private NSMutableArray* _members; NSMutableArray* _resources; + NSMutableDictionary* _configurations; } @property(nonatomic, strong, readonly) NSString* key; @@ -42,6 +45,9 @@ - (NSArray*) resources; - (NSArray*) members; +- (NSDictionary*) configurations; +- (XCBuildConfigurationList*)defaultConfiguration; + - (void) addMember:(XCSourceFile*)member; - (void) removeMemberWithKey:(NSString*)key; diff --git a/Source/Main/XCTarget.m b/Source/Main/XCTarget.m index dbf1c1b..61e868a 100755 --- a/Source/Main/XCTarget.m +++ b/Source/Main/XCTarget.m @@ -12,7 +12,8 @@ #import "XCTarget.h" #import "XCSourceFile.h" #import "XCProject.h" -#import "OCLogTemplate.h" +#import "XCBuildConfigurationList.h" +#import "Utils/XCMemoryUtils.h" /* ================================================================================================================== */ @interface XCTarget () @@ -34,8 +35,8 @@ @implementation XCTarget /* ================================================= Class Methods ================================================== */ + (XCTarget*) targetWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)name productName:(NSString*)productName productReference:(NSString*)productReference { - return [[XCTarget alloc] - initWithProject:project key:key name:name productName:productName productReference:productReference]; + return XCAutorelease([[XCTarget alloc] + initWithProject:project key:key name:name productName:productName productReference:productReference]) } @@ -44,8 +45,8 @@ - (id) initWithProject:(XCProject*)project key:(NSString*)key name:(NSString*)na productReference:(NSString*)productReference { self = [super init]; if (self) { - _project = project; - _key = key; + _project = XCRetain(project) + _key = [key copy]; _name = [name copy]; _productName = [productName copy]; _productReference = [productReference copy]; @@ -68,11 +69,40 @@ - (NSArray*) resources { } } } - NSSortDescriptor* sorter = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - return [_resources sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; + + return _resources; +} + +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_project) + XCRelease(_key) + XCRelease(_name) + XCRelease(_productName) + XCRelease(_productReference) + XCRelease(_members) + XCRelease(_resources) + XCRelease(_defaultConfigurationName) + + XCSuperDealloc } /* ================================================ Interface Methods =============================================== */ +- (NSArray *) configurations { + if (_configurations == nil) { + NSString *buildConfigurationRootSectionKey = [[[_project objects] objectForKey:_key] objectForKey:@"buildConfigurationList"]; + NSDictionary *buildConfigurationDictionary = [[_project objects] objectForKey:buildConfigurationRootSectionKey]; + _configurations = [[XCBuildConfigurationList buildConfigurationsFromDictionary:[buildConfigurationDictionary objectForKey:@"buildConfigurations"] inProject:_project] mutableCopy]; + _defaultConfigurationName = [[buildConfigurationDictionary objectForKey:@"defaultConfigurationName"] copy]; + } + + return XCAutorelease([_configurations copy]) +} + +- (XCBuildConfigurationList*)defaultConfiguration { + return [[self configurations] objectForKey:_defaultConfigurationName]; +} + - (NSArray*) members { if (_members == nil) { _members = [[NSMutableArray alloc] init]; @@ -81,7 +111,7 @@ - (NSArray*) members { if ([[buildPhase valueForKey:@"isa"] asMemberType] == PBXSourcesBuildPhase || [[buildPhase valueForKey:@"isa"] asMemberType] == PBXFrameworksBuildPhase) { for (NSString* buildFileKey in [buildPhase objectForKey:@"files"]) { - XCSourceFile* targetMember = [self buildFileWithKey:buildFileKey]; + XCSourceFile* targetMember = [_project fileWithKey:buildFileKey]; if (targetMember) { [_members addObject:[self buildFileWithKey:buildFileKey]]; } @@ -89,12 +119,10 @@ - (NSArray*) members { } } } - NSSortDescriptor* sorter = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - return [_members sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; + return _members; } - (void) addMember:(XCSourceFile*)member { - LogDebug(@"$$$$$$$$$$$$$$$$$$$$$$$$ start adding member: %@", member); [member becomeBuildFile]; NSDictionary* target = [[_project objects] objectForKey:_key]; @@ -106,9 +134,6 @@ - (void) addMember:(XCSourceFile*)member { if (![files containsObject:[member buildFileKey]]) { [files addObject:[member buildFileKey]]; } - else { - LogInfo(@"***WARNING*** Target %@ already includes %@", [self name], [member name]); - } [buildPhase setObject:files forKey:@"files"]; } @@ -198,6 +223,7 @@ - (XCSourceFile*) buildFileWithKey:(NSString*)theKey { } - (void) flagMembersAsDirty { + XCRelease(_members) _members = nil; } diff --git a/Source/Main/XCXibDefinition.m b/Source/Main/XCXibDefinition.m index 2a3f89c..fb57f33 100755 --- a/Source/Main/XCXibDefinition.m +++ b/Source/Main/XCXibDefinition.m @@ -9,7 +9,7 @@ // //////////////////////////////////////////////////////////////////////////////// #import "XCXibDefinition.h" - +#import "Utils/XCMemoryUtils.h" @implementation XCXibDefinition @@ -18,11 +18,11 @@ @implementation XCXibDefinition /* ================================================= Class Methods ================================================== */ + (XCXibDefinition*) xibDefinitionWithName:(NSString*)name { - return [[XCXibDefinition alloc] initWithName:name]; + return XCAutorelease([[XCXibDefinition alloc] initWithName:name]) } + (XCXibDefinition*) xibDefinitionWithName:(NSString*)name content:(NSString*)content { - return [[XCXibDefinition alloc] initWithName:name content:content]; + return XCAutorelease([[XCXibDefinition alloc] initWithName:name content:content]) } @@ -35,12 +35,20 @@ - (id) initWithName:(NSString*)name { - (id) initWithName:(NSString*)name content:(NSString*)content { self = [super init]; if (self) { - _name = name; - _content = content; + _name = [name copy]; + _content = [content copy]; } return self; } +/* ================================================== Deallocation ================================================== */ +- (void) dealloc { + XCRelease(_name) + XCRelease(_content) + + XCSuperDealloc +} + /* ================================================ Interface Methods =============================================== */ - (NSString*) xibFileName { return [_name stringByAppendingString:@".xib"]; diff --git a/Source/Main/XcodeMemberType.m b/Source/Main/XcodeMemberType.m index 1938837..d48e247 100755 --- a/Source/Main/XcodeMemberType.m +++ b/Source/Main/XcodeMemberType.m @@ -11,7 +11,7 @@ #import "XcodeMemberType.h" -#import "XCEnumUtils.h" +#import "Utils/XCEnumUtils.h" @implementation NSDictionary (XcodeMemberType) @@ -21,7 +21,7 @@ + (NSDictionary*) dictionaryWithProjectNodeTypesAsStrings { // This is the most vital operation on adding 500+ files // So, we caching this dictionary if (!_projectNodeTypesAsStrings) { - _projectNodeTypesAsStrings = [NSDictionary dictionaryWithObjectsAndKeys:boxEnum(PBXNilType), @"PBXNilType", + _projectNodeTypesAsStrings = [[NSDictionary alloc] initWithObjectsAndKeys:boxEnum(PBXNilType), @"PBXNilType", boxEnum(PBXBuildFile), @"PBXBuildFile", boxEnum(PBXContainerItemProxy), @"PBXContainerItemProxy", boxEnum(PBXCopyFilesBuildPhase), @"PBXCopyFilesBuildPhase", diff --git a/Source/Main/XcodeSourceFileType.m b/Source/Main/XcodeSourceFileType.m index 43b975c..7b32a3d 100755 --- a/Source/Main/XcodeSourceFileType.m +++ b/Source/Main/XcodeSourceFileType.m @@ -10,7 +10,7 @@ //////////////////////////////////////////////////////////////////////////////// #import "XcodeSourceFileType.h" -#import "XCEnumUtils.h" +#import "Utils/XCEnumUtils.h" @implementation NSDictionary (XcodeFileType) diff --git a/target b/target new file mode 100644 index 0000000..0517ef0 --- /dev/null +++ b/target @@ -0,0 +1,3 @@ +SOURCES = Source/Main/**/*.m +EXPORT = Source/Main/**/*.h +FRAMEWORKS = Cocoa diff --git a/xcode-editor.xcodeproj/project.pbxproj b/xcode-editor.xcodeproj/project.pbxproj index 826538b..c98e145 100644 --- a/xcode-editor.xcodeproj/project.pbxproj +++ b/xcode-editor.xcodeproj/project.pbxproj @@ -77,6 +77,9 @@ 6BE4B285147E6B610059E460 /* XCFrameworkDefinition.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BE4B285147E6B610059E45E /* XCFrameworkDefinition.m */; }; 6BE4B285147E6B610059E462 /* XCFrameworkDefinition.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BE4B285147E6B610059E461 /* XCFrameworkDefinition.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6BE9748E15AF0B31004472E2 /* OCLogTemplate.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BE9748D15AF0B31004472E2 /* OCLogTemplate.h */; }; + 923C35D715DFA9AF001AEE44 /* XCBuildConfigurationList.h in Headers */ = {isa = PBXBuildFile; fileRef = 923C35D515DFA9AF001AEE44 /* XCBuildConfigurationList.h */; }; + 923C35D815DFA9AF001AEE44 /* XCBuildConfigurationList.m in Sources */ = {isa = PBXBuildFile; fileRef = 923C35D615DFA9AF001AEE44 /* XCBuildConfigurationList.m */; }; + 923C35D915DFA9AF001AEE44 /* XCBuildConfigurationList.m in Sources */ = {isa = PBXBuildFile; fileRef = 923C35D615DFA9AF001AEE44 /* XCBuildConfigurationList.m */; }; BA79845028C69EFC6F98AFF5 /* XcodeEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = BA79848F199FA8B3F3DFA16E /* XcodeEditor.h */; }; E94DE11415443AC100C51253 /* HelloWorldLayer.header in Resources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C51252 /* HelloWorldLayer.header */; }; E94DE11415443AC100C51255 /* HelloWorldLayer.impl in Resources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C51254 /* HelloWorldLayer.impl */; }; @@ -86,10 +89,10 @@ E94DE11415443AC100C5125D /* XCSourceFileDefinition.h in Headers */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C5125C /* XCSourceFileDefinition.h */; settings = {ATTRIBUTES = (Public, ); }; }; E94DE11415443AC100C51260 /* XCSubProjectDefinition.m in Sources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C5125F /* XCSubProjectDefinition.m */; }; E94DE11415443AC100C51262 /* SubProjectDefinitionSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C51261 /* SubProjectDefinitionSpec.m */; }; - E94DE11415443AC100C51264 /* PBXBuildFile */ = {isa = PBXBuildFile; }; - E94DE11415443AC100C51265 /* PBXBuildFile */ = {isa = PBXBuildFile; }; - E94DE11415443AC100C51269 /* PBXBuildFile */ = {isa = PBXBuildFile; }; - E94DE11415443AC100C5126A /* PBXBuildFile */ = {isa = PBXBuildFile; }; + E94DE11415443AC100C51264 /* (null) in Sources */ = {isa = PBXBuildFile; }; + E94DE11415443AC100C51265 /* (null) in Sources */ = {isa = PBXBuildFile; }; + E94DE11415443AC100C51269 /* (null) in Sources */ = {isa = PBXBuildFile; }; + E94DE11415443AC100C5126A /* (null) in Sources */ = {isa = PBXBuildFile; }; E94DE11415443AC100C5126E /* XCProject+SubProject.m in Sources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C5126D /* XCProject+SubProject.m */; }; E94DE11415443AC100C5126F /* XCProject+SubProject.m in Sources */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C5126D /* XCProject+SubProject.m */; }; E94DE11415443AC100C51271 /* XCProject+SubProject.h in Headers */ = {isa = PBXBuildFile; fileRef = E94DE11415443AC100C51270 /* XCProject+SubProject.h */; }; @@ -177,6 +180,9 @@ 6BE4B285147E6B610059E45E /* XCFrameworkDefinition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCFrameworkDefinition.m; sourceTree = ""; }; 6BE4B285147E6B610059E461 /* XCFrameworkDefinition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCFrameworkDefinition.h; sourceTree = ""; }; 6BE9748D15AF0B31004472E2 /* OCLogTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCLogTemplate.h; sourceTree = ""; }; + 923C35D515DFA9AF001AEE44 /* XCBuildConfigurationList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCBuildConfigurationList.h; sourceTree = ""; }; + 923C35D615DFA9AF001AEE44 /* XCBuildConfigurationList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCBuildConfigurationList.m; sourceTree = ""; }; + 92E640F015EB65500077FD86 /* XCMemoryUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCMemoryUtils.h; sourceTree = ""; }; BA79848F199FA8B3F3DFA16E /* XcodeEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XcodeEditor.h; sourceTree = ""; }; E94DE11415443AC100C51252 /* HelloWorldLayer.header */ = {isa = PBXFileReference; lastKnownFileType = file.header; path = HelloWorldLayer.header; sourceTree = ""; }; E94DE11415443AC100C51254 /* HelloWorldLayer.impl */ = {isa = PBXFileReference; lastKnownFileType = file.impl; path = HelloWorldLayer.impl; sourceTree = ""; }; @@ -246,6 +252,8 @@ 6B3AD01D14F8A3AC00BCFE81 /* XCFileOperationQueue.h */, 6B3AD01A14F8A3AC00BCFE81 /* XCClassDefinition.m */, 6B3AD01914F8A3AC00BCFE81 /* XCClassDefinition.h */, + 923C35D615DFA9AF001AEE44 /* XCBuildConfigurationList.m */, + 923C35D515DFA9AF001AEE44 /* XCBuildConfigurationList.h */, 6B65941914F8A56C00F65AEC /* Resources */, E94DE11415443AC100C51258 /* Utils */, ); @@ -383,6 +391,7 @@ 6B3AD02214F8A3AC00BCFE81 /* XCKeyBuilder.m */, 6B3AD02114F8A3AC00BCFE81 /* XCKeyBuilder.h */, 6BE4B285147E6B610059E455 /* XCEnumUtils.h */, + 92E640F015EB65500077FD86 /* XCMemoryUtils.h */, ); path = Utils; sourceTree = ""; @@ -412,6 +421,7 @@ E94DE11415443AC100C51271 /* XCProject+SubProject.h in Headers */, 6BE9748E15AF0B31004472E2 /* OCLogTemplate.h in Headers */, BA79845028C69EFC6F98AFF5 /* XcodeEditor.h in Headers */, + 923C35D715DFA9AF001AEE44 /* XCBuildConfigurationList.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -563,9 +573,10 @@ 6B019F6F154832C400122D48 /* XCAbstractDefinition.m in Sources */, E94DE11415443AC100C5125B /* XCSourceFileDefinition.m in Sources */, 6B4B61221588A070003639E8 /* XCSubProjectDefinition.m in Sources */, - E94DE11415443AC100C51265 /* PBXBuildFile */, - E94DE11415443AC100C5126A /* PBXBuildFile */, + E94DE11415443AC100C51265 /* (null) in Sources */, + E94DE11415443AC100C5126A /* (null) in Sources */, E94DE11415443AC100C5126F /* XCProject+SubProject.m in Sources */, + 923C35D915DFA9AF001AEE44 /* XCBuildConfigurationList.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -594,9 +605,10 @@ E94DE11415443AC100C5125A /* XCSourceFileDefinition.m in Sources */, E94DE11415443AC100C51260 /* XCSubProjectDefinition.m in Sources */, E94DE11415443AC100C51262 /* SubProjectDefinitionSpec.m in Sources */, - E94DE11415443AC100C51264 /* PBXBuildFile */, - E94DE11415443AC100C51269 /* PBXBuildFile */, + E94DE11415443AC100C51264 /* (null) in Sources */, + E94DE11415443AC100C51269 /* (null) in Sources */, E94DE11415443AC100C5126E /* XCProject+SubProject.m in Sources */, + 923C35D815DFA9AF001AEE44 /* XCBuildConfigurationList.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -667,8 +679,6 @@ 6B55224414EA723700494CF3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; DSTROOT = /tmp/xcodeproj.dst; FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; GCC_GENERATE_TEST_COVERAGE_FILES = YES; @@ -699,8 +709,6 @@ 6B55224514EA723700494CF3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; DSTROOT = /tmp/xcodeproj.dst; FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; GCC_GENERATE_TEST_COVERAGE_FILES = YES; @@ -732,7 +740,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -750,7 +758,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; }; name = Debug; }; @@ -758,7 +765,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -769,7 +776,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.7; - SDKROOT = macosx; }; name = Release; };