Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

added the possibility to pass a xcodeproj directly to appledoc (no further options NEEDED but possible) #248

Merged
merged 2 commits into from

3 participants

@Daij-Djan

it will try to do the right thing :D

it will open Xcode file and look for basic project settings and it will then build a docket and install it

Daij-Djan added some commits
@Daij-Djan Daij-Djan made it possible to just give the path to an xcodeproject to appledoc.
it will try to do the right thing :D

- it will open Xcode file and look for basic project settings and it will then build a docket and install it

Signed-off-by: Dominik Pich <Dominik@pich.info>
6b8302c
@Daij-Djan Daij-Djan fixed error handling
Signed-off-by: Dominik Pich <Dominik@pich.info>
d78cdb4
@tomaz tomaz merged commit 047e182 into tomaz:master
@tomaz
Owner

Wow, this is cool one, thanks!

@lukaskubanek

Are you going to add a description of this functionality to your site? Or could you please explain here, how does it work?

@tomaz
Owner
@lukaskubanek

Thanks for your response!

@Daij-Djan

yip @tomaz thats the gist - note that it is set to build and install a dockset by default
all settings should override it

@tomaz
Owner

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 7, 2012
  1. @Daij-Djan

    made it possible to just give the path to an xcodeproject to appledoc.

    Daij-Djan authored
    it will try to do the right thing :D
    
    - it will open Xcode file and look for basic project settings and it will then build a docket and install it
    
    Signed-off-by: Dominik Pich <Dominik@pich.info>
Commits on Sep 8, 2012
  1. @Daij-Djan

    fixed error handling

    Daij-Djan authored
    Signed-off-by: Dominik Pich <Dominik@pich.info>
This page is out of date. Refresh to see the latest.
View
34 Application/GBAppledocApplication.m
@@ -15,6 +15,7 @@
#import "GBGenerator.h"
#import "GBApplicationSettingsProvider.h"
#import "GBAppledocApplication.h"
+#import "DDXcodeProjectFile.h"
static NSString *kGBArgInputPath = @"input";
static NSString *kGBArgOutputPath = @"output";
@@ -101,6 +102,7 @@ - (void)validateSettingsAndArguments:(NSArray *)arguments;
- (NSString *)standardizeCurrentDirectoryForPath:(NSString *)path;
- (NSString *)combineBasePath:(NSString *)base withRelativePath:(NSString *)path;
+- (void)injectXcodeSettingsFromArguments:(NSArray *)arguments;
- (void)injectGlobalSettingsFromArguments:(NSArray *)arguments;
- (void)injectProjectSettingsFromArguments:(NSArray *)arguments;
- (void)overrideSettingsWithGlobalSettingsFromPath:(NSString *)path;
@@ -318,6 +320,7 @@ - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser
{ nil, 0, 0 },
};
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ [self injectXcodeSettingsFromArguments:arguments];
[self injectGlobalSettingsFromArguments:arguments];
[self injectProjectSettingsFromArguments:arguments];
[optionParser addOptionsFromTable:options];
@@ -455,7 +458,36 @@ - (NSString *)combineBasePath:(NSString *)base withRelativePath:(NSString *)path
return [base stringByAppendingPathComponent:path];
}
-#pragma mark Global and project settings handling
+#pragma mark Xcode, Global and project settings handling
+
+- (void)injectXcodeSettingsFromArguments:(NSArray *)arguments {
+ //check if even deal with a project
+ NSString *path = [arguments objectAtIndex:1];
+ if(![path.pathExtension isEqualToString:@"xcodeproj"])
+ return;
+
+ //parse the file and get a representation of it
+ NSError *error = nil;
+ DDXcodeProjectFile *file = [DDXcodeProjectFile xcodeProjectFileWithPath:path error:&error];
+ if(!file) {
+ NSLog(@"Failed to parse pbx at %@: %@", path, error);
+ return;
+ }
+
+ //set basic vars
+ [self setProjectName:file.name];
+ [self setProjectCompany:file.company];
+
+ //prepare docset
+ [self setCreateDocset:YES];
+ [self setInstallDocset:YES];
+ [self setDocsetBundleName:file.name];
+ [self setCompanyId:[file.company stringByAppendingFormat:@".%@", file.name].lowercaseString];
+
+ //set output path to be next to project
+ [self.additionalInputPaths addObject:file.projectRoot];
+ [self setOutput:file.projectRoot];
+}
- (void)injectGlobalSettingsFromArguments:(NSArray *)arguments {
// This is where we override factory defaults (factory defaults with global templates). This needs to be sent before giving DDCli a chance to go through parameters! DDCli will "take care" (or more correct: it's KVC messages will) of overriding with command line arguments. Note that we scan the arguments backwards to get the latest template value - this is what we'll get with DDCli later on anyway. If no template path is given, check predefined paths.
View
39 Common/DDXcodeProjectFile.h
@@ -0,0 +1,39 @@
+//
+// DDXcodeProjectFile.h
+// appledoc
+//
+// Created by Dominik Pich on 9/4/12.
+// Copyright (c) 2012 Gentle Bytes. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/** @file DDXcodeProjectFile.h */
+
+/**
+ * reads an xcode 4 Project file and provides an in memory representation
+ * @warning WHICH cannot be saved at the moment
+ * @warning Does only provide the fundamental project settings right now as that's all I need ATM :D
+ */
+@interface DDXcodeProjectFile : NSObject
+
+@property(readonly) NSString *path;
+@property(readonly) NSDictionary *dictionary;
+
+@property(readonly) NSString *name;
+@property(readonly) NSString *minimumVersion;
+@property(readonly) NSString *company;
+@property(readonly) NSString *projectRoot;
+@property(readonly) NSString *classPrefix;
+@property(readonly) NSString *developmentRegion;
+
+/**
+ * an array of 1-N dicts for all files found in the project. Each dictionary contains 'path' and 'type'
+ * the path is resolved to an absolute path
+ */
+@property(readonly) NSArray *files;
+
++ (id)xcodeProjectFileWithPath:(NSString*)path error:(NSError**)pError;
++ (id)xcodeProjectFileWithDictionary:(NSDictionary*)dict error:(NSError**)pError;
+
+@end
View
234 Common/DDXcodeProjectFile.m
@@ -0,0 +1,234 @@
+//
+// DDXcodeProjectFile.m
+// appledoc
+//
+// Created by Dominik Pich on 9/4/12.
+// Copyright (c) 2012 Gentle Bytes. All rights reserved.
+//
+
+#import "DDXcodeProjectFile.h"
+
+@interface DDXcodeProjectFile () {
+ NSMutableArray *_mutableFilesBuffer;
+}
+
+@property(readwrite) NSString *path;
+@property(readwrite) NSDictionary *dictionary;
+
+@property(readwrite) NSString *name;
+@property(readwrite) NSString *minimumVersion;
+@property(readwrite) NSString *projectRoot;
+@property(readwrite) NSString *company;
+@property(readwrite) NSString *classPrefix;
+@property(readwrite) NSString *developmentRegion;
+@property(readwrite) NSArray *files;
+
+- (BOOL)parse:(NSError**)pError;
+
+- (id)initWithPath:(NSString*)path;
+- (id)initWithName:(NSString*)name andDictionary:(NSDictionary*)dict;
+@end
+
+@implementation DDXcodeProjectFile
+
+#pragma mark -
+
+- (id)initWithPath:(NSString*)path {
+ id pbxpath = nil;
+
+ if([[path lastPathComponent] isEqualToString:@"project.pbxproj"]) {
+ pbxpath = path;
+ path = path.stringByDeletingLastPathComponent;
+ }
+ else {
+ //path = path
+ pbxpath = [path stringByAppendingPathComponent:@"project.pbxproj"];
+ }
+
+ BOOL isDir = NO;
+ NSAssert([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir], @"project doesnt exist");
+ NSAssert(isDir, @"project should be a directory");
+ NSAssert([[NSFileManager defaultManager] fileExistsAtPath:pbxpath isDirectory:nil], @"project has no pbx xml file");
+
+ if(self) {
+ self.path = pbxpath;
+ self.name = path.lastPathComponent.stringByDeletingPathExtension;
+ }
+
+ return self;
+}
+
+- (id)initWithName:(NSString*)name andDictionary:(NSDictionary*)dict {
+ self = [super init];
+
+ if(self) {
+ self.name = name;
+ self.dictionary = dict;
+ }
+
+ return self;
+}
+
++ (id)xcodeProjectFileWithPath:(NSString*)path error:(NSError**)pError {
+ id file = [[[self class] alloc] initWithPath:path];
+ if(file) {
+ if([file parse:pError]) {
+ return file;
+ }
+ }
+ return nil;
+}
+
++ (id)xcodeProjectFileWithDictionary:(NSDictionary*)dict error:(NSError**)pError {
+ id file = [[[self class] alloc] initWithDictionary:dict];
+ if(file) {
+ if([file parse:pError]) {
+ return file;
+ }
+ }
+ return nil;
+}
+
+#pragma mark - main parse
+
+- (BOOL)parse:(NSError**)pError {
+ NSAssert(self.path.length || self.dictionary.count, @"we should have a non-empty path or non-empty dictionary");
+
+ //get initial dictionary
+ if(self.path.length) {
+ self.dictionary = [NSDictionary dictionaryWithContentsOfFile:self.path];
+ if(!self.dictionary) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:@"cannot make plist from file contents"}];
+ return NO;
+ }
+ }
+ if(!self.dictionary) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:@"cannot make plist from file contents"}];
+ return NO;
+ }
+
+ //get main objects dictionary
+ NSDictionary *objects = self.dictionary[@"objects"];
+ if(![objects isKindOfClass:[NSDictionary class]]) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:@"cannot find main objects dictionary"}];
+ return NO;
+ }
+
+ //set up _mutableFilesBuffer which will get filled in the parsing process.. or not :D
+ _mutableFilesBuffer = [NSMutableArray arrayWithCapacity:objects.count/2];
+
+ //handle each object that can appear in a method found via string to SEL
+ for (NSDictionary *object in objects.allValues) {
+ if(![object isKindOfClass:[NSDictionary class]] || !object[@"isa"]) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"cannot handle object %@", object]}];
+ return NO;
+ }
+
+ //get method by isa
+ SEL method = [self methodNameForIsa:object[@"isa"]];
+ if(!method) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"cannot handle isa %@. Selector: %@", object[@"isa"], NSStringFromSelector(method)]}];
+ return NO;
+ }
+
+ //if it doesnt respond to the method, log it and continue for now
+ if(![self respondsToSelector:method]) {
+ NSLog(@"Warn: dont handle %@", NSStringFromSelector(method));
+ continue;
+ }
+
+ //call the reflected method
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+ NSError *suberror = [self performSelector:method withObject:object];
+#pragma clang diagnostic pop
+
+ //exit on error
+ if(suberror) {
+ *pError = suberror;
+ return NO;
+ }
+ }
+
+ //check mandatory... 1 file at least
+ if( !_mutableFilesBuffer.count ) {
+ *pError = [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:@"cannot find manatory attributes in plist from file contents"}];
+ return NO;
+ }
+
+ //resolve all
+ NSError *suberror = [self resolveFiles:_mutableFilesBuffer];
+ if(suberror) {
+ *pError = suberror;
+ return NO;
+ }
+
+ //save buffer to property
+ self.files = [NSArray arrayWithArray:_mutableFilesBuffer];
+
+ return YES;
+}
+
+- (SEL)methodNameForIsa:(NSString*)pbxIsa {
+ NSString *name = [NSString stringWithFormat:@"parse%@:", pbxIsa];
+ return NSSelectorFromString(name);
+}
+
+- (NSError*)resolveFiles:(NSMutableArray*)files {
+
+ return nil;
+}
+
+#pragma mark - parse individual objects
+
+//- (NSError*)parsePBXBuildFile:(NSDictionary*)dict {
+// return nil;
+//}
+//- (NSError*)parsePBXSourcesBuildPhase:(NSDictionary*)dict {
+// return nil;
+//}
+
+// we only care about those for now
+
+- (NSError*)parsePBXProject:(NSDictionary*)dict {
+ if(!dict[@"attributes"]) {
+ return [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"PBXProject without attributes: %@", dict]}];
+ }
+
+ self.classPrefix = dict[@"attributes"][@"CLASSPREFIX"];
+ self.company = dict[@"attributes"][@"ORGANIZATIONNAME"];
+ self.developmentRegion = dict[@"developmentRegion"];
+ self.minimumVersion = dict[@"compatibilityVersion"];
+
+ if(dict[@"projectRoot"]) {
+ if(self.path.length)
+ self.projectRoot = [self.path.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent stringByAppendingPathComponent:dict[@"projectRoot"]];
+ else
+ self.projectRoot = dict[@"projectRoot"];
+ }
+
+ if(!self.company || !self.projectRoot) {
+ return [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"PBXProject missing mandatory attributes: %@", dict]}];
+ }
+
+ return nil;
+}
+
+- (NSError*)parsePBXFileReference:(NSDictionary*)dict {
+ if(!dict[@"lastKnownFileType"] && dict[@"explicitFileType"]) {
+ NSMutableDictionary *mdict = dict.mutableCopy;
+ mdict[@"lastKnownFileType"] = dict[@"explicitFileType"];
+ dict = mdict;
+ }
+
+ if(!dict[@"path"] || !dict[@"lastKnownFileType"]) {
+ return [NSError errorWithDomain:@"DDXcodeProjectFile" code:0 userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"PBXFileReference without path/type: %@", dict]}];
+ }
+
+ //add the path - TO BE resolved later :D
+ [_mutableFilesBuffer addObject:@{@"path": dict[@"path"], @"type": dict[@"lastKnownFileType"]}];
+
+ return nil; //no error
+}
+
+@end
View
8 appledoc.xcodeproj/project.pbxproj
@@ -210,6 +210,8 @@
73FC741D11FE215E00AAD0B9 /* GBMethodData.m in Sources */ = {isa = PBXBuildFile; fileRef = 73FC741C11FE215E00AAD0B9 /* GBMethodData.m */; };
73FC742D11FE274300AAD0B9 /* GBMethodArgument.m in Sources */ = {isa = PBXBuildFile; fileRef = 73FC742C11FE274300AAD0B9 /* GBMethodArgument.m */; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ B498BCDF15F6250500183EB5 /* DDXcodeProjectFile.m in Sources */ = {isa = PBXBuildFile; fileRef = B498BCDE15F6250500183EB5 /* DDXcodeProjectFile.m */; };
+ B498BCE015F6250500183EB5 /* DDXcodeProjectFile.m in Sources */ = {isa = PBXBuildFile; fileRef = B498BCDE15F6250500183EB5 /* DDXcodeProjectFile.m */; };
D818BAC0152039DC00B26451 /* GHUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 733EA0F1122BDC5B0060CBDE /* GHUnit.framework */; };
D818BACE15203AA700B26451 /* GHUnit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 733EA0F1122BDC5B0060CBDE /* GHUnit.framework */; };
D818BACF15203AA700B26451 /* OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 73FC6EDF11FCE01E00AAD0B9 /* OCMock.framework */; };
@@ -508,6 +510,8 @@
73FC742C11FE274300AAD0B9 /* GBMethodArgument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBMethodArgument.m; sourceTree = "<group>"; };
73FC743511FE2CEB00AAD0B9 /* GBMethodDataTesting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBMethodDataTesting.m; sourceTree = "<group>"; };
8DD76FA10486AA7600D96B5E /* appledoc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = appledoc; sourceTree = BUILT_PRODUCTS_DIR; };
+ B498BCDD15F6250500183EB5 /* DDXcodeProjectFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDXcodeProjectFile.h; sourceTree = "<group>"; };
+ B498BCDE15F6250500183EB5 /* DDXcodeProjectFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDXcodeProjectFile.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -759,6 +763,8 @@
73D54C9411F8D1CC00CCDDB0 /* Common */ = {
isa = PBXGroup;
children = (
+ B498BCDD15F6250500183EB5 /* DDXcodeProjectFile.h */,
+ B498BCDE15F6250500183EB5 /* DDXcodeProjectFile.m */,
73D54CA711F8D27F00CCDDB0 /* GBLog.h */,
73D54CA811F8D27F00CCDDB0 /* GBLog.m */,
73397A2612A5070700EDC035 /* GBTask.h */,
@@ -1271,6 +1277,7 @@
73E1B7D4130BE72100E3D710 /* GBCommentsProcessor-RegistrationsTesting.m in Sources */,
73E1B7D6130BE7C000E3D710 /* GBCommentsProcessor-PreprocessingTesting.m in Sources */,
73E0CF46131047E700FAFEC0 /* GBCommentsProcessor-MarkdownTesting.m in Sources */,
+ B498BCE015F6250500183EB5 /* DDXcodeProjectFile.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1353,6 +1360,7 @@
73AF4ECC130938F3001152DB /* GBCommentComponentsList.m in Sources */,
73FAC0F9130BCB6F00F22475 /* GBCommentArgument.m in Sources */,
73C4C8611377DFF70024FA77 /* GBExitCodes.m in Sources */,
+ B498BCDF15F6250500183EB5 /* DDXcodeProjectFile.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Something went wrong with that request. Please try again.