Permalink
Browse files

Cleaned up HeaderDoc parsing code and made it optional. References #95

…and #163.

As comment preprocessing method in `GBTokenizer` became quite large, I divided it into separate methods by taking out header doc preprocessing. Also made header doc preprocessing optional and disabled by default (except the bare minimum covered by #95). To enable it, use `--preprocess-headerdoc` command line switch. The reason for opting it out by default is amount of preprocessing that could break things for existing appledoc users. Probably just me being paranoid, but better safe than sorry :)
  • Loading branch information...
1 parent 178a2ce commit 2e063c0e1ecb2dbf260d0346879939f90a39fe32 @tomaz committed Dec 24, 2011
View
@@ -17,6 +17,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>744</string>
+ <string>748</string>
</dict>
</plist>
@@ -40,6 +40,7 @@
static NSString *kGBArgExitCodeThreshold = @"exit-threshold";
static NSString *kGBArgRepeatFirstParagraph = @"repeat-first-par";
+static NSString *kGBArgPreprocessHeaderDoc = @"preprocess-headerdoc";
static NSString *kGBArgUseSingleStar = @"use-single-star";
static NSString *kGBArgKeepUndocumentedObjects = @"keep-undocumented-objects";
static NSString *kGBArgKeepUndocumentedMembers = @"keep-undocumented-members";
@@ -271,6 +272,7 @@ - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser
{ kGBArgKeepUndocumentedMembers, 0, DDGetoptNoArgument },
{ kGBArgFindUndocumentedMembersDocumentation, 0, DDGetoptNoArgument },
{ kGBArgRepeatFirstParagraph, 0, DDGetoptNoArgument },
+ { kGBArgPreprocessHeaderDoc, 0, DDGetoptNoArgument },
{ kGBArgUseSingleStar, 0, DDGetoptNoArgument },
{ kGBArgMergeCategoriesToClasses, 0, DDGetoptNoArgument },
{ kGBArgKeepMergedCategoriesSections, 0, DDGetoptNoArgument },
@@ -671,6 +673,7 @@ - (void)setKeepUndocumentedObjects:(BOOL)value { self.settings.keepUndocumentedO
- (void)setKeepUndocumentedMembers:(BOOL)value { self.settings.keepUndocumentedMembers = value; }
- (void)setSearchUndocumentedDoc:(BOOL)value { self.settings.findUndocumentedMembersDocumentation = value; }
- (void)setRepeatFirstPar:(BOOL)value { self.settings.repeatFirstParagraphForMemberDescription = value; }
+- (void)setPreprocessHeaderdoc:(BOOL)value { self.settings.preprocessHeaderDoc = value; }
- (void)setUseSingleStar:(BOOL)value { self.settings.useSingleStarForBold = value; }
- (void)setMergeCategories:(BOOL)value { self.settings.mergeCategoriesToClasses = value; }
- (void)setKeepMergedSections:(BOOL)value { self.settings.keepMergedCategoriesSections = value; }
@@ -681,6 +684,7 @@ - (void)setNoKeepUndocumentedMembers:(BOOL)value { self.settings.keepUndocumente
- (void)setNoSearchUndocumentedDoc:(BOOL)value { self.settings.findUndocumentedMembersDocumentation = !value; }
- (void)setNoRepeatFirstPar:(BOOL)value { self.settings.repeatFirstParagraphForMemberDescription = !value; }
- (void)setNoUseSingleStar:(BOOL)value { self.settings.useSingleStarForBold = !value; }
+- (void)setNoPreprocessHeaderdoc:(BOOL)value { self.settings.preprocessHeaderDoc = !value; }
- (void)setNoMergeCategories:(BOOL)value { self.settings.mergeCategoriesToClasses = !value; }
- (void)setNoKeepMergedSections:(BOOL)value { self.settings.keepMergedCategoriesSections = !value; }
- (void)setNoPrefixMergedSections:(BOOL)value { self.settings.prefixMergedCategoriesSectionsWithCategoryName = !value; }
@@ -232,6 +232,12 @@ extern id kGBCustomDocumentIndexDescKey;
*/
@property (assign) BOOL repeatFirstParagraphForMemberDescription;
+/** Indicates whether we should preprocess header doc style comments or not.
+
+ If `YES`, appledoc will try to do best to handle header doc comments while preprocessing.
+ */
+@property (assign) BOOL preprocessHeaderDoc;
+
/** Indicates whether we should treat single stars as bold markers or not.
If `YES`, single star markers (`*text*`) should be treated as bold markers (`**text**`), otherwise not. This is mainly used for backwards compatibility, but should be disabled as it can cause unexpected issues, such as converting unordered lists into bold etc.
@@ -79,6 +79,7 @@ - (id)init {
self.installDocSet = YES;
self.publishDocSet = NO;
self.repeatFirstParagraphForMemberDescription = YES;
+ self.preprocessHeaderDoc = NO;
self.useSingleStarForBold = NO;
self.keepIntermediateFiles = NO;
self.cleanupOutputPathBeforeRunning = NO;
@@ -593,6 +594,7 @@ - (NSString *)versionIdentifier {
@synthesize docsetPackageFilename;
@synthesize repeatFirstParagraphForMemberDescription;
+@synthesize preprocessHeaderDoc;
@synthesize useSingleStarForBold;
@synthesize keepUndocumentedObjects;
@synthesize keepUndocumentedMembers;
@@ -139,7 +139,7 @@ - (NSDictionary *)appledocData {
result = [[NSMutableDictionary alloc] init];
[result setObject:@"appledoc" forKey:@"tool"];
[result setObject:@"2.0.5" forKey:@"version"];
- [result setObject:@"744" forKey:@"build"];
+ [result setObject:@"748" forKey:@"build"];
[result setObject:@"http://appledoc.gentlebytes.com" forKey:@"homepage"];
}
return result;
View
@@ -17,6 +17,8 @@ @interface GBTokenizer ()
- (BOOL)consumeComments;
- (NSString *)commentValueFromString:(NSString *)value isMultiline:(BOOL)multiline;
+- (NSString *)lineByPreprocessingHeaderDocDirectives:(NSString *)line;
+- (NSArray *)linesByReorderingHeaderDocDirectives:(NSArray *)lines;
- (NSArray *)allTokensFromTokenizer:(PKTokenizer *)tokenizer;
@property (retain) NSString *filename;
@property (retain) NSString *input;
@@ -245,26 +247,26 @@ - (BOOL)consumeComments {
- (NSString *)commentValueFromString:(NSString *)value isMultiline:(BOOL)multiline {
if ([value length] == 0) return nil;
NSArray *lines = [value componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
- NSMutableArray *comments = [NSMutableArray arrayWithCapacity:[lines count]];
+ NSMutableArray *strippedLines = [NSMutableArray arrayWithCapacity:[lines count]];
// First pass: removes delimiters. We simply detect 3+ delimiter chars in any combination. If removing delimiter yields empty line, discard it.
[lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
NSString *stripped = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *delimited = [stripped stringByReplacingOccurrencesOfRegex:self.commentDelimiterRegex withString:@""];
if ([stripped length] > [delimited length]) {
- if ([delimited length] > 0) [comments addObject:delimited];
+ if ([delimited length] > 0) [strippedLines addObject:delimited];
return;
}
- [comments addObject:line];
+ [strippedLines addObject:line];
}];
// If all lines start with a *, ignore the prefix. Note that we ignore first line as it can only contain /** and text! We also ignore last line as if it only contains */
NSString *prefixRegex = @"(?m:^\\s*\\*[ ]*)";
- __block BOOL stripPrefix = ([comments count] > 1);
+ __block BOOL stripPrefix = ([strippedLines count] > 1);
if (stripPrefix) {
- [comments enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
+ [strippedLines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
NSString *stripped = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
- if (idx == [comments count]-1 && [stripped length] == 0) {
+ if (idx == [strippedLines count]-1 && [stripped length] == 0) {
return;
}
if ((!multiline || idx > 0) && ![stripped isMatchedByRegex:prefixRegex]) {
@@ -273,76 +275,70 @@ - (NSString *)commentValueFromString:(NSString *)value isMultiline:(BOOL)multili
}
}];
}
-
- /*
- The following brings HeaderDoc comments in line with AppleDoc
-
- --------------------------------
- */
-
- // make sure that @param and @return is placed at the end (after abstract etc.)
- NSMutableArray *reorderedParams = [NSMutableArray array];
- NSMutableArray *reorderedNonParams = [NSMutableArray array];
-
- NSRegularExpression *regexParam = [NSRegularExpression regularExpressionWithPattern:@"^\\s*@(param|result|return)" options:NSRegularExpressionDotMatchesLineSeparators error:nil];
- NSRegularExpression *regexNonParam = [NSRegularExpression regularExpressionWithPattern:@"^\\s*@[a-z]" options:NSRegularExpressionDotMatchesLineSeparators error:nil];
-
- BOOL isParamBlock = NO;
- for (NSString *aLine in comments) {
-
- if ([regexParam numberOfMatchesInString:aLine options:0 range:NSMakeRange(0, [aLine length])] > 0) {
- isParamBlock = YES;
- } else if ([regexNonParam numberOfMatchesInString:aLine options:0 range:NSMakeRange(0, [aLine length])] > 0) {
- isParamBlock = NO;
- }
-
- if (isParamBlock) {
- [reorderedParams addObject:aLine];
- } else {
- [reorderedNonParams addObject:aLine];
- }
- }
-
- [reorderedNonParams addObjectsFromArray:reorderedParams];
-
- comments = [reorderedNonParams copy];
-
-
+
+ // Preprocess header doc directives.
+ NSArray *preprocessedLines = [self linesByReorderingHeaderDocDirectives:strippedLines];
// Finally remove common line prefix and a single prefix space (but leave multiple spaces to properly handle space prefixed example blocks!) and compose all objects into final comment.
NSCharacterSet *spacesSet = [NSCharacterSet characterSetWithCharactersInString:@" "];
NSString *spacesPrefixRegex = @"^ {2,}";
NSString *tabPrefixRegex = @"^\t";
NSMutableString *result = [NSMutableString stringWithCapacity:[value length]];
- [comments enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
+ [preprocessedLines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
if (stripPrefix) line = [line stringByReplacingOccurrencesOfRegex:prefixRegex withString:@""];
if (![line isMatchedByRegex:spacesPrefixRegex] && ![line isMatchedByRegex:tabPrefixRegex]) line = [line stringByTrimmingCharactersInSet:spacesSet];
-
-
- // remove the entire line when it contains @method or property or class
- line = [line stringByReplacingOccurrencesOfRegex:@"(?m:@(protocol|method|property|class).*$)" withString:@""];
-
- // remove unsupported headerDoc words
- line = [line stringByReplacingOccurrencesOfRegex:@"(?m:^\\s*@(discussion|abstract))\\s?" withString:@"\n"];
-
- // replace methodgroup with name
- line = [line stringByReplacingOccurrencesOfRegex:@"(?:@(methodgroup|group))" withString:@"@name"];
-
+ line = [self lineByPreprocessingHeaderDocDirectives:line];
[result appendString:line];
- if (idx < [comments count] - 1) [result appendString:@"\n"];
+ if (idx < [strippedLines count] - 1) [result appendString:@"\n"];
}];
-
- /*
- The previous lines bring HeaderDoc comments in line with AppleDoc
-
- --------------------------------
- */
-
+
// If the result is empty string, return nil, otherwise return the comment string.
if ([result length] == 0) return nil;
return result;
}
+- (NSString *)lineByPreprocessingHeaderDocDirectives:(NSString *)line {
+ if (!self.settings.preprocessHeaderDoc) return line;
+
+ // Remove the entire line when it contains @method or property or class.
+ line = [line stringByReplacingOccurrencesOfRegex:@"(?m:@(protocol|method|property|class).*$)" withString:@""];
+
+ // Remove unsupported headerDoc words.
+ line = [line stringByReplacingOccurrencesOfRegex:@"(?m:^\\s*@(discussion|abstract))\\s?" withString:@"\n"];
+
+ // Replace methodgroup with name.
+ line = [line stringByReplacingOccurrencesOfRegex:@"(?:@(methodgroup|group))" withString:@"@name"];
+ return line;
+}
+
+- (NSArray *)linesByReorderingHeaderDocDirectives:(NSArray *)lines {
+ if (!self.settings.preprocessHeaderDoc) return lines;
+
+ // Make sure that @param and @return is placed at the end (after abstract etc.)
+ NSMutableArray *reorderedParams = [NSMutableArray array];
+ NSMutableArray *reorderedNonParams = [NSMutableArray array];
+ NSRegularExpression *directiveExpression = [NSRegularExpression regularExpressionWithPattern:@"^\\s*@(param|result|return)" options:NSRegularExpressionDotMatchesLineSeparators error:nil];
+ NSRegularExpression *lineExpression = [NSRegularExpression regularExpressionWithPattern:@"^\\s*@[a-z]" options:NSRegularExpressionDotMatchesLineSeparators error:nil];
+
+ BOOL isParamBlock = NO;
+ for (NSString *line in lines) {
+ if ([directiveExpression numberOfMatchesInString:line options:0 range:NSMakeRange(0, [line length])] > 0) {
+ isParamBlock = YES;
+ } else if ([lineExpression numberOfMatchesInString:line options:0 range:NSMakeRange(0, [line length])] > 0) {
+ isParamBlock = NO;
+ }
+
+ if (isParamBlock) {
+ [reorderedParams addObject:line];
+ } else {
+ [reorderedNonParams addObject:line];
+ }
+ }
+
+ [reorderedNonParams addObjectsFromArray:reorderedParams];
+ return reorderedNonParams;
+}
+
- (void)resetComments {
GBLogDebug(@"Resetting comments...");
[self.lastCommentBuilder setString:@""];
@@ -257,6 +257,15 @@ - (void)testRepeatFirstParagraph_shouldAssignValueToSettings {
assertThatBool(settings2.repeatFirstParagraphForMemberDescription, equalToBool(NO));
}
+- (void)testPreprocessHeaderDoc_shouldAssignValueToSettings {
+ // setup & execute
+ GBApplicationSettingsProvider *settings1 = [self settingsByRunningWithArgs:@"--preprocess-headerdoc", nil];
+ GBApplicationSettingsProvider *settings2 = [self settingsByRunningWithArgs:@"--no-preprocess-headerdoc", nil];
+ // verify
+ assertThatBool(settings1.preprocessHeaderDoc, equalToBool(YES));
+ assertThatBool(settings2.preprocessHeaderDoc, equalToBool(NO));
+}
+
- (void)testUseSingleStarForBold_shouldAssignValueToSettings {
// setup & execute
GBApplicationSettingsProvider *settings1 = [self settingsByRunningWithArgs:@"--use-single-star", nil];

0 comments on commit 2e063c0

Please sign in to comment.