Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added extra options to exclude symbols, and local auto-generated cross-references #397

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Application/GBAppledocApplication.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
static NSString *kGBArgKeepMergedCategoriesSections = @"keep-merged-sections";
static NSString *kGBArgPrefixMergedCategoriesSectionsWithCategoryName = @"prefix-merged-sections";
static NSString *kGBArgUseCodeOrder = @"use-code-order";
static NSString *kGBArgIgnoreSymbol = @"ignore-symbol";
static NSString *kGBArgRequireLeaderForLocalCrossRefs = @"require-leader-for-local-crossrefs";

static NSString *kGBArgExplicitCrossRef = @"explicit-crossref";
static NSString *kGBArgCrossRefFormat = @"crossref-format";
Expand Down Expand Up @@ -305,6 +307,9 @@ - (void)application:(DDCliApplication *)app willParseOptions:(DDGetoptLongParser
{ GBNoArg(kGBArgKeepMergedCategoriesSections), 0, DDGetoptNoArgument },
{ GBNoArg(kGBArgPrefixMergedCategoriesSectionsWithCategoryName), 0, DDGetoptNoArgument },
{ GBNoArg(kGBArgUseCodeOrder), 0, DDGetoptNoArgument },
{ kGBArgIgnoreSymbol, 0, DDGetoptRequiredArgument },
{ kGBArgRequireLeaderForLocalCrossRefs, 0, DDGetoptNoArgument },
{ GBNoArg(kGBArgRequireLeaderForLocalCrossRefs), 0, DDGetoptNoArgument },

{ kGBArgWarnOnMissingOutputPath, 0, DDGetoptNoArgument },
{ kGBArgWarnOnMissingCompanyIdentifier, 0, DDGetoptNoArgument },
Expand Down Expand Up @@ -816,6 +821,11 @@ - (void)setNoKeepMergedSections:(BOOL)value { self.settings.keepMergedCategories
- (void)setNoPrefixMergedSections:(BOOL)value { self.settings.prefixMergedCategoriesSectionsWithCategoryName = !value; }
- (void)setUseCodeOrder:(BOOL)value { self.settings.useCodeOrder = value; }
- (void)setNoUseCodeOrder:(BOOL)value { self.settings.useCodeOrder = !value; }
- (void)setIgnoreSymbol:(NSString *)glob {
[self.settings.ignoredSymbols addObject:glob];
}
-(void)setRequireLeaderForLocalCrossrefs:(BOOL)value { self.settings.requireLeaderForLocalCrossRefs = value; }
-(void)setNoRequireLeaderForLocalCrossrefs:(BOOL)value { self.settings.requireLeaderForLocalCrossRefs = !value; }

- (void)setWarnMissingOutputPath:(BOOL)value { self.settings.warnOnMissingOutputPathArgument = value; }
- (void)setWarnMissingCompanyId:(BOOL)value { self.settings.warnOnMissingCompanyIdentifier = value; }
Expand Down Expand Up @@ -942,6 +952,8 @@ - (void)printSettingsAndArguments:(NSArray *)arguments {
ddprintf(@"--%@ = %@\n", kGBArgPrefixMergedCategoriesSectionsWithCategoryName, PRINT_BOOL(self.settings.prefixMergedCategoriesSectionsWithCategoryName));
ddprintf(@"--%@ = %@\n", kGBArgCrossRefFormat, self.settings.commentComponents.crossReferenceMarkersTemplate);
ddprintf(@"--%@ = %@\n", kGBArgUseCodeOrder, self.settings.useCodeOrder);
for (NSString *glob in self.settings.ignoredSymbols) ddprintf(@"--%@ = %@\n", kGBArgIgnoreSymbol, glob);
ddprintf(@"--%@ = %@\n", kGBArgRequireLeaderForLocalCrossRefs, PRINT_BOOL(self.settings.requireLeaderForLocalCrossRefs));
ddprintf(@"--%@ = %ld\n", kGBArgExitCodeThreshold, self.settings.exitCodeThreshold);
ddprintf(@"\n");

Expand Down Expand Up @@ -1011,6 +1023,8 @@ - (void)printHelp {
PRINT_USAGE(@" ", kGBArgPrefixMergedCategoriesSectionsWithCategoryName, @"", @"[b] Prefix merged sections with category name");
PRINT_USAGE(@" ", kGBArgExplicitCrossRef, @"", @"[b] Shortcut for explicit default cross ref template");
PRINT_USAGE(@" ", kGBArgUseCodeOrder, @"", @"[b] Order sections by the order specified in the input files");
PRINT_USAGE(@" ", kGBArgIgnoreSymbol, @"<glob>", @"[*] A glob to match against symbols. If a symbol matches, it will not be included in the output.");
PRINT_USAGE(@" ", kGBArgRequireLeaderForLocalCrossRefs, @"", @"[b] If true, only auto-link local symbol references that begin with '-' or '+'.");
PRINT_USAGE(@" ", kGBArgCrossRefFormat, @"<string>", @"Cross reference template regex");
PRINT_USAGE(@" ", kGBArgExitCodeThreshold, @"<number>", @"Exit code threshold below which 0 is returned");
ddprintf(@"\n");
Expand Down
12 changes: 12 additions & 0 deletions Application/GBApplicationSettingsProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,18 @@ NSString *NSStringFromGBPublishedFeedFormats(GBPublishedFeedFormats format);
*/
@property (assign) BOOL useCodeOrder;

/** A set of globs to be matched against each input symbol to determine whether the symbol should be ignored

*/
@property (retain) NSMutableSet* ignoredSymbols;

/** Specifies whether auto-linking for 'local' cross references requires the symbol to begin with '-' or '+'

If 'YES' then auto-linking of local symbols will only happen if the symbol is written in the comment with a leading '+' or '-'. This reduces false-positives, where links are created out of common words, because there are local symbols named after common words (e.g 'and')

*/
@property (assign) BOOL requireLeaderForLocalCrossRefs;

/** Indicates whteher local methods and properties cross references texts should be prefixed when used in related items list.

If `YES`, instance methods are prefixed with `-`, class methods with `+` and properties with `@property` when used as cross reference in related items list (i.e. see also section for methods). If `NO`, no prefix is used.
Expand Down
4 changes: 4 additions & 0 deletions Application/GBApplicationSettingsProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ - (id)init {
self.keepMergedCategoriesSections = NO;
self.prefixMergedCategoriesSectionsWithCategoryName = NO;
self.useCodeOrder = NO;
self.ignoredSymbols = [ NSMutableSet set ];
self.requireLeaderForLocalCrossRefs = NO;

self.prefixLocalMembersInRelatedItemsList = YES;
self.embedCrossReferencesWhenProcessingMarkdown = YES;
Expand Down Expand Up @@ -679,6 +681,8 @@ - (NSString *)versionIdentifier {
@synthesize keepMergedCategoriesSections;
@synthesize prefixMergedCategoriesSectionsWithCategoryName;
@synthesize useCodeOrder;
@synthesize ignoredSymbols;
@synthesize requireLeaderForLocalCrossRefs;

@synthesize prefixLocalMembersInRelatedItemsList;
@synthesize embedCrossReferencesWhenProcessingMarkdown;
Expand Down
3 changes: 2 additions & 1 deletion Application/GBCommentComponentsProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@
The result of the method depends on the templated value: if the value is `YES`, the string includes template from `crossReferenceMarkersTemplate`, otherwise it only contains "pure" regex. The first option should be used for in-text cross references detection, while the second for `crossReferenceRegex` matching.

@param templated If `YES` templated regex is returned, otherwise pure one.
@param requireLeader If 'YES', the regex will only match local member cross references with a '+' or '-' leader. Making this a requirement will reduce false links, but may lose some valid links.
@return Returns the regex used for matching cross reference.
*/
- (NSString *)localMemberCrossReferenceRegex:(BOOL)templated;
- (NSString *)localMemberCrossReferenceRegex:(BOOL)templated requireLeader:(BOOL)requireLeader;

/** Returns the regex used for matching (possible) category cross reference with capture 1 containing category name.

Expand Down
18 changes: 15 additions & 3 deletions Application/GBCommentComponentsProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,23 @@ - (NSString *)remoteMemberCrossReferenceRegex:(BOOL)templated {
}
}

- (NSString *)localMemberCrossReferenceRegex:(BOOL)templated {
- (NSString *)localMemberCrossReferenceRegex:(BOOL)templated requireLeader:(BOOL)requireLeader {
if (templated) {
GBRETURN_ON_DEMAND([self crossReferenceRegexForRegex:[self localMemberCrossReferenceRegex:NO]]);
static NSString *regexLeaderRequired = nil;
static NSString *regexLeaderNotRequired = nil;
if (!regexLeaderRequired) {
regexLeaderRequired = [self crossReferenceRegexForRegex:[self localMemberCrossReferenceRegex:NO requireLeader:YES]];
regexLeaderNotRequired = [ self crossReferenceRegexForRegex:[self localMemberCrossReferenceRegex:NO requireLeader:NO]];
}
return requireLeader ? regexLeaderRequired : regexLeaderNotRequired;
} else {
GBRETURN_ON_DEMAND(@"([+-]?)([^>,.;!?()\\s]+)");
static NSString *regexLeaderRequired = nil;
static NSString *regexLeaderNotRequired = nil;
if (!regexLeaderRequired) {
regexLeaderRequired = @"([+-])([^>,.;!?()\\s]+)";
regexLeaderNotRequired = @"([+-]?)([^>,.;!?()\\s]+)";
}
return requireLeader ? regexLeaderRequired : regexLeaderNotRequired;
}
}

Expand Down
8 changes: 8 additions & 0 deletions Common/NSString+GBString.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,12 @@
*/
- (NSUInteger)numberOfLinesInRange:(NSRange)range;


/** Glob matching

@param glob The glob to match against the receiver. '*' matches any number of characters, '?' matches any one character
@return Returns whether glob matches the receiver
*/
- (BOOL)matchesGlob:(NSString *)glob;

@end
44 changes: 44 additions & 0 deletions Common/NSString+GBString.m
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,50 @@ - (NSUInteger)numberOfLinesInRange:(NSRange)range {
return [lines count];
}

- (BOOL)matchesGlob:(NSString *)glob
{
NSUInteger strIdxForCurrentStarMatch = 0, afterLastStarIdx = NSNotFound;
NSUInteger strIdx = 0, globIdx = 0;
NSUInteger strLen = self.length;
NSUInteger globLen = glob.length;

while (strIdx < strLen && ([glob characterAtIndex:globIdx] != '*')) {
if (([glob characterAtIndex:globIdx] != [self characterAtIndex:strIdx]) &&
([glob characterAtIndex:globIdx] != '?')) {
return NO;
}
globIdx++;
strIdx++;
}

while (strIdx < strLen) {
if ([glob characterAtIndex:globIdx] == '*') {
globIdx++;
if (globIdx == globLen) {
return YES;
}
afterLastStarIdx = globIdx;
strIdxForCurrentStarMatch = strIdx + 1;
}
else if (([glob characterAtIndex:globIdx] == [self characterAtIndex:strIdx]) ||
([glob characterAtIndex:globIdx] == '?')) {
globIdx++;
strIdx++;
}
else if (afterLastStarIdx != NSNotFound) {
globIdx = afterLastStarIdx;
strIdx = strIdxForCurrentStarMatch++;
}
else {
return NO;
}
}

while (globIdx < globLen && [glob characterAtIndex:globIdx] == '*') {
globIdx++;
}
return (globIdx == globLen);
}
@end

#pragma mark -
Expand Down
32 changes: 32 additions & 0 deletions Parsing/GBObjectiveCParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ - (void)updateLastComment:(GBComment **)comment sectionComment:(GBComment **)sec

@interface GBObjectiveCParser (DefinitionParsing)

- (BOOL)isIgnoredSymbol:(NSString*)symbol;
- (void)matchClassDefinition;
- (void)matchCategoryDefinition;
- (void)matchExtensionDefinition;
Expand Down Expand Up @@ -150,9 +151,24 @@ - (void)updateLastComment:(GBComment **)comment sectionComment:(GBComment **)sec

@implementation GBObjectiveCParser (DefinitionParsing)

- (BOOL)isIgnoredSymbol:(NSString*)symbol {
for (NSString* glob in settings.ignoredSymbols) {
if ([symbol matchesGlob:glob]) {
return YES;
}
}
return NO;
}

- (void)matchClassDefinition {
// @interface CLASSNAME
NSString *className = [[self.tokenizer lookahead:1] stringValue];
if ([self isIgnoredSymbol:className]) {
GBLogInfo(@"Skipping ignored class %@", className);
[self.tokenizer consumeTo:@"@end" usingBlock:^(PKToken *token, BOOL *consume, BOOL *stop) { }];
return;
}

GBClassData *class = [GBClassData classDataWithName:className];
class.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:class];
Expand All @@ -174,6 +190,12 @@ - (void)matchCategoryDefinition {
// @interface CLASSNAME ( CATEGORYNAME )
NSString *className = [[self.tokenizer lookahead:1] stringValue];
NSString *categoryName = [[self.tokenizer lookahead:3] stringValue];
NSString* fullName = [NSString stringWithFormat:@"%@(%@)",className,categoryName];
if ([self isIgnoredSymbol:fullName]) {
GBLogInfo(@"Skipping ignored category %@", fullName);
[self.tokenizer consumeTo:@"@end" usingBlock:^(PKToken *token, BOOL *consume, BOOL *stop) { }];
return;
}
GBCategoryData *category = [GBCategoryData categoryDataWithName:categoryName className:className];
category.includeInOutput = self.includeInOutput;
[self registerSourceInfoFromCurrentTokenToObject:category];
Expand All @@ -192,6 +214,11 @@ - (void)matchCategoryDefinition {
- (void)matchExtensionDefinition {
// @interface CLASSNAME ( )
NSString *className = [[self.tokenizer lookahead:1] stringValue];
if ([self isIgnoredSymbol:className]) {
GBLogInfo(@"Skipping ignored class extension %@", className);
[self.tokenizer consumeTo:@"@end" usingBlock:^(PKToken *token, BOOL *consume, BOOL *stop) { }];
return;
}
GBCategoryData *extension = [GBCategoryData categoryDataWithName:nil className:className];
extension.includeInOutput = self.includeInOutput;
GBLogVerbose(@"Matched %@() extension definition at line %lu.", className, extension.prefferedSourceInfo.lineNumber);
Expand All @@ -210,6 +237,11 @@ - (void)matchExtensionDefinition {
- (void)matchProtocolDefinition {
// @protocol PROTOCOLNAME
NSString *protocolName = [[self.tokenizer lookahead:1] stringValue];
if ([self isIgnoredSymbol:protocolName]) {
GBLogInfo(@"Skipping ignored protocol %@", protocolName);
[self.tokenizer consumeTo:@"@end" usingBlock:^(PKToken *token, BOOL *consume, BOOL *stop) { }];
return;
}
GBProtocolData *protocol = [GBProtocolData protocolDataWithName:protocolName];
protocol.includeInOutput = self.includeInOutput;
GBLogVerbose(@"Matched %@ protocol definition at line %lu.", protocolName, protocol.prefferedSourceInfo.lineNumber);
Expand Down
2 changes: 1 addition & 1 deletion Processing/GBCommentsProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ - (GBCrossRefData *)dataForLocalMemberLinkInString:(NSString *)string searchRang
if (!self.currentContext) return nil;

BOOL templated = (flags & GBProcessingFlagRelatedItem) == 0;
NSString *regex = [self.components localMemberCrossReferenceRegex:templated];
NSString *regex = [self.components localMemberCrossReferenceRegex:templated requireLeader:self.settings.requireLeaderForLocalCrossRefs ];
NSArray *components = [string captureComponentsMatchedByRegex:regex range:searchRange];
if ([components count] == 0) return nil;

Expand Down
19 changes: 19 additions & 0 deletions Testing/GBApplicationTesting.m
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,25 @@ - (void)testExitCodeThreshold_shouldAssignValueToSettings {
assertThatInteger(settings.exitCodeThreshold, equalToInteger(2));
}

- (void)testIgnoreSymbol_shouldAssignValueToSettings {
// setup & execute
GBApplicationSettingsProvider *settings = [self settingsByRunningWithArgs:@"--ignore-symbol", @"*deprecated*", @"--ignore-symbol", @"DummyClass?", nil];
// verify - note that ignore should not convert dot to current path; this would prevent .m being parsed properly!
assertThatInteger([settings.ignoredSymbols count], equalToInteger(2));
assertThatBool([settings.ignoredSymbols containsObject:@"*deprecated*"], equalToBool(YES));
assertThatBool([settings.ignoredSymbols containsObject:@"DummyClass?"], equalToBool(YES));
}

- (void)testRequireLeaderForLocalCrossRefs_shouldAssignValueToSettings {
// setup & execute
GBApplicationSettingsProvider *settings1 = [self settingsByRunningWithArgs:@"--require-leader-for-local-crossrefs", nil];
GBApplicationSettingsProvider *settings2 = [self settingsByRunningWithArgs:@"--no-require-leader-for-local-crossrefs", nil];
// verify
assertThatBool(settings1.requireLeaderForLocalCrossRefs, equalToBool(YES));
assertThatBool(settings2.requireLeaderForLocalCrossRefs, equalToBool(NO));
}


#pragma mark Warnings settings testing

- (void)testWarnOnMissingOutputPath_shouldAssignValueToSettings {
Expand Down