Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added support for excluding paths from the output. #133

Merged
merged 2 commits into from

2 participants

@lhunath

This is useful if you only want to generate documentation for certain
sources but those sources depend on other sources that should not have
documentation generated for them. With this feature, you add all
sources as input and exclude certain sources from output generation. It
will hide warnings on excluded sources, not generate output for them,
but they will be used for merging with your included sources (eg.
inheritance etc.)

lhunath added some commits
@lhunath lhunath Fixed a crash when trying to append a nil value. dbf7903
@lhunath lhunath Added support for excluding paths from the output.
This is useful if you only want to generate documentation for certain
sources but those sources depend on other sources that should not have
documentation generated for them.  With this feature, you add all
sources as input and exclude certain sources from output generation.  It
will hide warnings on excluded sources, not generate output for them,
but they will be used for merging with your included sources (eg.
inheritance etc.)
e0f477a
@tomaz
Owner

Might be confusing with --ignore option, but is useful, so I'm merging it to main branch, thanks!

@tomaz tomaz merged commit 0fb82df into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 19, 2011
  1. @lhunath
  2. @lhunath

    Added support for excluding paths from the output.

    lhunath authored
    This is useful if you only want to generate documentation for certain
    sources but those sources depend on other sources that should not have
    documentation generated for them.  With this feature, you add all
    sources as input and exclude certain sources from output generation.  It
    will hide warnings on excluded sources, not generate output for them,
    but they will be used for merging with your included sources (eg.
    inheritance etc.)
This page is out of date. Refresh to see the latest.
View
7 Application/GBAppledocApplication.m
@@ -24,6 +24,7 @@
static NSString *kGBArgIndexDescPath = @"index-desc";
static NSString *kGBArgIncludePath = @"include";
static NSString *kGBArgIgnorePath = @"ignore";
+static NSString *kGBArgExcludeOutputPath = @"exclude-output";
static NSString *kGBArgProjectName = @"project-name";
static NSString *kGBArgProjectVersion = @"project-version";
@@ -220,6 +221,7 @@ - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser
{ kGBArgOutputPath, 'o', DDGetoptRequiredArgument },
{ kGBArgTemplatesPath, 't', DDGetoptRequiredArgument },
{ kGBArgIgnorePath, 'i', DDGetoptRequiredArgument },
+ { kGBArgExcludeOutputPath, 'x', DDGetoptRequiredArgument },
{ kGBArgIncludePath, 's', DDGetoptRequiredArgument },
{ kGBArgIndexDescPath, 0, DDGetoptRequiredArgument },
{ kGBArgDocSetInstallPath, 0, DDGetoptRequiredArgument },
@@ -601,6 +603,9 @@ - (void)setIgnore:(NSString *)path {
if ([path hasPrefix:@"*"]) path = [path substringFromIndex:1];
[self.settings.ignoredPaths addObject:path];
}
+- (void)setExcludeOutput:(NSString *)path {
+ [self.settings.excludeOutputPaths addObject:path];
+}
- (void)setProjectName:(NSString *)value { self.settings.projectName = value; }
- (void)setProjectVersion:(NSString *)value { self.settings.projectVersion = value; }
@@ -745,6 +750,7 @@ - (void)printSettingsAndArguments:(NSArray *)arguments {
ddprintf(@"--%@ = %@\n", kGBArgIndexDescPath, self.settings.indexDescriptionPath);
for (NSString *path in self.settings.includePaths) ddprintf(@"--%@ = %@\n", kGBArgIncludePath, path);
for (NSString *path in self.settings.ignoredPaths) ddprintf(@"--%@ = %@\n", kGBArgIgnorePath, path);
+ for (NSString *path in self.settings.excludeOutputPaths) ddprintf(@"--%@ = %@\n", kGBArgExcludeOutputPath, path);
ddprintf(@"--%@ = %@\n", kGBArgDocSetInstallPath, self.settings.docsetInstallPath);
ddprintf(@"--%@ = %@\n", kGBArgDocSetUtilPath, self.settings.docsetUtilPath);
ddprintf(@"\n");
@@ -819,6 +825,7 @@ - (void)printHelp {
PRINT_USAGE(@" ", kGBArgDocSetInstallPath, @"<path>", @"DocSet installation path");
PRINT_USAGE(@"-s,", kGBArgIncludePath, @"<path>", @"Include static doc(s) at path");
PRINT_USAGE(@"-i,", kGBArgIgnorePath, @"<path>", @"Ignore given path");
+ PRINT_USAGE(@"-x,", kGBArgExcludeOutputPath, @"<path>", @"Exclude given path from output");
PRINT_USAGE(@" ", kGBArgIndexDescPath, @"<path>", @"File including main index description");
ddprintf(@"\n");
ddprintf(@"PROJECT INFO\n");
View
6 Application/GBApplicationSettingsProvider.h
@@ -164,6 +164,12 @@ extern id kGBCustomDocumentIndexDescKey;
*/
@property (retain) NSMutableSet *ignoredPaths;
+/** The list of all full or partial paths to exclude from output generation.
+
+ Source code in these paths is still parsed and possibly used for copying to classes not in the excludeOutputPaths.
+ */
+@property (retain) NSMutableSet *excludeOutputPaths;
+
///---------------------------------------------------------------------------------------
/// @name Behavior handling
///---------------------------------------------------------------------------------------
View
2  Application/GBApplicationSettingsProvider.m
@@ -72,6 +72,7 @@ - (id)init {
self.indexDescriptionPath = nil;
self.includePaths = [NSMutableSet set];
self.ignoredPaths = [NSMutableSet set];
+ self.excludeOutputPaths = [NSMutableSet set];
self.createHTML = YES;
self.createDocSet = YES;
@@ -570,6 +571,7 @@ - (NSString *)versionIdentifier {
@synthesize includePaths;
@synthesize indexDescriptionPath;
@synthesize ignoredPaths;
+@synthesize excludeOutputPaths;
@synthesize docsetBundleIdentifier;
@synthesize docsetBundleName;
View
3  Generating/GBHTMLOutputGenerator.m
@@ -56,6 +56,7 @@ - (BOOL)generateOutputWithStore:(id)store error:(NSError **)error {
- (BOOL)processClasses:(NSError **)error {
for (GBClassData *class in self.store.classes) {
+ if (!class.includeInOutput) continue;
GBLogInfo(@"Generating output for class %@...", class);
NSDictionary *vars = [self.variablesProvider variablesForClass:class withStore:self.store];
NSString *output = [self.htmlObjectTemplate renderObject:vars];
@@ -72,6 +73,7 @@ - (BOOL)processClasses:(NSError **)error {
- (BOOL)processCategories:(NSError **)error {
for (GBCategoryData *category in self.store.categories) {
+ if (!category.includeInOutput) continue;
GBLogInfo(@"Generating output for category %@...", category);
NSDictionary *vars = [self.variablesProvider variablesForCategory:category withStore:self.store];
NSString *output = [self.htmlObjectTemplate renderObject:vars];
@@ -88,6 +90,7 @@ - (BOOL)processCategories:(NSError **)error {
- (BOOL)processProtocols:(NSError **)error {
for (GBProtocolData *protocol in self.store.protocols) {
+ if (!protocol.includeInOutput) continue;
GBLogInfo(@"Generating output for protocol %@...", protocol);
NSDictionary *vars = [self.variablesProvider variablesForProtocol:protocol withStore:self.store];
NSString *output = [self.htmlObjectTemplate renderObject:vars];
View
4 Generating/GBHTMLTemplateVariablesProvider.m
@@ -426,6 +426,7 @@ - (NSArray *)classesForIndex {
NSArray *classes = [self.store classesSortedByName];
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[classes count]];
for (GBClassData *class in classes) {
+ if (!class.includeInOutput) continue;
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithCapacity:2];
[data setObject:[self hrefForObject:class fromObject:nil] forKey:@"href"];
[data setObject:class.nameOfClass forKey:@"title"];
@@ -438,6 +439,7 @@ - (NSArray *)categoriesForIndex {
NSArray *categories = [self.store categoriesSortedByName];
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[categories count]];
for (GBCategoryData *category in categories) {
+ if (!category.includeInOutput) continue;
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithCapacity:2];
[data setObject:[self hrefForObject:category fromObject:nil] forKey:@"href"];
[data setObject:category.idOfCategory forKey:@"title"];
@@ -450,6 +452,7 @@ - (NSArray *)protocolsForIndex {
NSArray *protocols = [self.store protocolsSortedByName];
NSMutableArray *result = [NSMutableArray arrayWithCapacity:[protocols count]];
for (GBProtocolData *protocol in protocols) {
+ if (!protocol.includeInOutput) continue;
NSMutableDictionary *data = [NSMutableDictionary dictionaryWithCapacity:2];
[data setObject:[self hrefForObject:protocol fromObject:nil] forKey:@"href"];
[data setObject:protocol.nameOfProtocol forKey:@"title"];
@@ -462,6 +465,7 @@ - (NSArray *)classesForHierarchy {
// This returns the array of all root classes, each class containing further arrays of subclasses and so on. Ussually root classes array only contains single NSObject class, but can also include all root classes (not derived from NSObject). The algorithm for creating hierarhy is not state of the art, but it's quite simple and effective: for each class we iterate over it's whole hierarchy until we arrive at it's root class, creating an flat list of hierarchy for this class. Then we use the flat list to add all unknown class names to the hierarchy dictionary, together with all subclasses. When we process all classes like this, we have a dictionary with proper inheritance.
NSMutableDictionary *hierarchy = [NSMutableDictionary dictionaryWithCapacity:[self.store.classes count]];
for (GBClassData *class in [self.store.classes allObjects]) {
+ if (!class.includeInOutput) continue;
// Build the flat list of class hierarchy up to the root class. The flat lists array starts with root and ends with current class. Note how we treat unknown classes as root classes - if a class doesn't have a pointer to superclass, but does have it's name, we add the name to the flat list. Although this does end with usable hierarhcy, it does leave things open for improvements (i.e. deriving from NSView will not create the hierarchy all the way down to NSObject, but will instead use NSView as a root view, besides NSObject).
GBClassData *c = class;
NSMutableArray *flatlist = [NSMutableArray array];
View
4 Model/GBModelBase.h
@@ -16,6 +16,7 @@
@private
NSMutableSet *_sourceInfos;
NSMutableDictionary *_sourceInfosByFilenames;
+ BOOL _includeInOutput;
}
///---------------------------------------------------------------------------------------
@@ -128,4 +129,7 @@
*/
@property (copy) NSString *htmlReferenceName;
+/** Whether output should be generated for this class. If `NO`, this class is purely made available for the processing of other classes. */
+@property (assign) BOOL includeInOutput;
+
@end
View
2  Model/GBModelBase.m
@@ -19,6 +19,7 @@ - (id)init {
if (self) {
_sourceInfos = [[NSMutableSet alloc] init];
_sourceInfosByFilenames = [[NSMutableDictionary alloc] init];
+ _includeInOutput = YES;
}
return self;
}
@@ -103,5 +104,6 @@ - (BOOL)isTopLevelObject {
@synthesize parentObject;
@synthesize htmlLocalReference;
@synthesize htmlReferenceName;
+@synthesize includeInOutput = _includeInOutput;
@end
View
23 Parsing/GBObjectiveCParser.m
@@ -21,6 +21,7 @@ - (PKTokenizer *)tokenizerWithInputString:(NSString *)input;
@property (retain) GBTokenizer *tokenizer;
@property (retain) GBStore *store;
@property (retain) GBApplicationSettingsProvider *settings;
+@property (assign) BOOL includeInOutput;
@end
@@ -92,6 +93,21 @@ - (void)parseObjectsFromString:(NSString *)input sourceFile:(NSString *)filename
GBLogDebug(@"Parsing objective-c objects...");
self.store = store;
self.tokenizer = [GBTokenizer tokenizerWithSource:[self tokenizerWithInputString:input] filename:filename settings:self.settings];
+ self.includeInOutput = YES;
+ for (NSString *excludeOutputPath in self.settings.excludeOutputPaths) {
+ if ([filename isEqualToString:excludeOutputPath]) {
+ self.includeInOutput = NO;
+ break;
+ }
+
+ NSString *excludeOutputDir = excludeOutputPath;
+ if (![excludeOutputDir hasSuffix:@"/"])
+ excludeOutputDir = [NSString stringWithFormat:@"%@/", excludeOutputDir];
+ if ([filename hasPrefix:excludeOutputDir]) {
+ self.includeInOutput = NO;
+ break;
+ }
+ }
while (![self.tokenizer eof]) {
if (![self matchNextObject]) {
[self.tokenizer consume:1];
@@ -111,6 +127,7 @@ - (PKTokenizer *)tokenizerWithInputString:(NSString *)input {
@synthesize tokenizer;
@synthesize settings;
@synthesize store;
+@synthesize includeInOutput;
@end
@@ -122,6 +139,7 @@ - (void)matchClassDefinition {
// @interface CLASSNAME
NSString *className = [[self.tokenizer lookahead:1] stringValue];
GBClassData *class = [GBClassData classDataWithName:className];
+ class.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:class];
GBLogDebug(@"Matched %@ class definition at line %lu.", className, class.prefferedSourceInfo.lineNumber);
[self registerLastCommentToObject:class];
@@ -138,6 +156,7 @@ - (void)matchCategoryDefinition {
NSString *className = [[self.tokenizer lookahead:1] stringValue];
NSString *categoryName = [[self.tokenizer lookahead:3] stringValue];
GBCategoryData *category = [GBCategoryData categoryDataWithName:categoryName className:className];
+ category.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:category];
GBLogVerbose(@"Matched %@(%@) category definition at line %lu.", className, categoryName, category.prefferedSourceInfo.lineNumber);
[self registerLastCommentToObject:category];
@@ -151,6 +170,7 @@ - (void)matchExtensionDefinition {
// @interface CLASSNAME ( )
NSString *className = [[self.tokenizer lookahead:1] stringValue];
GBCategoryData *extension = [GBCategoryData categoryDataWithName:nil className:className];
+ extension.includeInOutput = self.includeInOutput;
GBLogVerbose(@"Matched %@() extension definition at line %lu.", className, extension.prefferedSourceInfo.lineNumber);
[self registerSourceInfoFromCurrentTokenToObject:extension];
[self registerLastCommentToObject:extension];
@@ -164,6 +184,7 @@ - (void)matchProtocolDefinition {
// @protocol PROTOCOLNAME
NSString *protocolName = [[self.tokenizer lookahead:1] stringValue];
GBProtocolData *protocol = [GBProtocolData protocolDataWithName:protocolName];
+ protocol.includeInOutput = self.includeInOutput;
GBLogVerbose(@"Matched %@ protocol definition at line %lu.", protocolName, protocol.prefferedSourceInfo.lineNumber);
[self registerSourceInfoFromCurrentTokenToObject:protocol];
[self registerLastCommentToObject:protocol];
@@ -289,6 +310,7 @@ - (void)matchClassDeclaration {
// @implementation CLASSNAME
NSString *className = [[self.tokenizer lookahead:1] stringValue];
GBClassData *class = [GBClassData classDataWithName:className];
+ class.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:class];
GBLogVerbose(@"Matched %@ class declaration at line %lu.", className, class.prefferedSourceInfo.lineNumber);
[self registerLastCommentToObject:class];
@@ -302,6 +324,7 @@ - (void)matchCategoryDeclaration {
NSString *className = [[self.tokenizer lookahead:1] stringValue];
NSString *categoryName = [[self.tokenizer lookahead:3] stringValue];
GBCategoryData *category = [GBCategoryData categoryDataWithName:categoryName className:className];
+ category.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:category];
GBLogVerbose(@"Matched %@(%@) category declaration at line %lu.", className, categoryName, category.prefferedSourceInfo.lineNumber);
[self registerLastCommentToObject:category];
View
3  Parsing/GBTokenizer.m
@@ -194,7 +194,8 @@ - (BOOL)consumeComments {
}
// Append string value to current comment and proceed with next token.
- [self.lastCommentBuilder appendString:value];
+ if (value)
+ [self.lastCommentBuilder appendString:value];
self.tokenIndex++;
}
View
7 Processing/GBProcessor.m
@@ -197,7 +197,8 @@ - (void)processParametersFromComment:(GBComment *)comment matchingMethod:(GBMeth
[names enumerateObjectsUsingBlock:^(NSString *name, NSUInteger idx, BOOL *stop) {
GBCommentArgument *parameter = [parameters objectForKey:name];
if (!parameter) {
- GBLogXWarn(comment.sourceInfo, @"%@: Description for parameter '%@' missing for %@!", comment.sourceInfo, name, method);
+ if (method.includeInOutput)
+ GBLogXWarn(comment.sourceInfo, @"%@: Description for parameter '%@' missing for %@!", comment.sourceInfo, name, method);
return;
}
[sorted addObject:parameter];
@@ -210,7 +211,7 @@ - (void)processParametersFromComment:(GBComment *)comment matchingMethod:(GBMeth
[description appendString:parameter.argumentName];
[sorted addObject:parameter];
}];
- if (self.settings.warnOnMissingMethodArgument) GBLogXWarn(comment.sourceInfo, @"%@: %ld unknown parameter descriptions (%@) found for %@", comment.sourceInfo, [parameters count], description, method);
+ if (self.settings.warnOnMissingMethodArgument && method.includeInOutput) GBLogXWarn(comment.sourceInfo, @"%@: %ld unknown parameter descriptions (%@) found for %@", comment.sourceInfo, [parameters count], description, method);
}
// Finaly re-register parameters to the comment if necessary (no need if there's only one parameter).
@@ -384,6 +385,8 @@ - (void)mergeKnownCategoriesFromStore {
#pragma mark Helper methods
- (void)validateCommentsForObjectAndMembers:(GBModelBase *)object {
+ if (!object.includeInOutput) return;
+
// Checks if the object is commented and warns if not. This validates given object and all it's members comments! The reason for doing it together is due to the fact that we first process all members and then handle the object. At that point we can even remove the object if not documented. So we can't validate members before as we don't know whether they will be deleted together with their parent object too...
if (![self isCommentValid:object.comment] && self.settings.warnOnUndocumentedObject) GBLogXWarn(object.prefferedSourceInfo, @"%@ is not documented!", object);
Something went wrong with that request. Please try again.