Skip to content

Commit

Permalink
Fixed methods and sections merging for GBMethodsProvider. Closes #73.
Browse files Browse the repository at this point in the history
The problem was in merging code always creating section for each merged method if not found in the original. This lead to creation of "Other methods" section when merging implementation into definition. This situation is properly handled now by only creating sections for methods not found in the original.
  • Loading branch information
tomaz committed Mar 1, 2011
1 parent 30d4e04 commit a0ed655
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
29 changes: 20 additions & 9 deletions Model/GBMethodsProvider.m
Expand Up @@ -158,19 +158,30 @@ - (void)mergeDataFromMethodsProvider:(GBMethodsProvider *)source {
// If a method with the same selector is found while merging from source, we should check if the type also matches. If so, we can merge the data from the source's method. However if the type doesn't match, we should ignore the method alltogether (ussually this is due to custom property implementation). We should probably deal with this scenario more inteligently, but it seems it works...
if (!source || source == self) return;
GBLogDebug(@"%@: Merging methods from %@...", _parent, source->_parent);

// First merge all existing methods regardless of section and prepare the list of all new methods.
NSMutableArray *newMethods = [NSMutableArray array];
[source.methods enumerateObjectsUsingBlock:^(GBMethodData *sourceMethod, NSUInteger idx, BOOL *stop) {
GBMethodData *existingMethod = [self methodBySelector:sourceMethod.methodSelector];
if (!existingMethod) {
[newMethods addObject:sourceMethod];
return;
}
[existingMethod mergeDataFromObject:sourceMethod];
}];
if ([newMethods count] == 0) return;

// Second merge all sections; only use sections for methods that were not registered yet! Note that we need to remember current section so that we restore it later on.
GBMethodSectionData *previousSection = _registeringSection;
[source.sections enumerateObjectsUsingBlock:^(GBMethodSectionData *sourceSection, NSUInteger idx, BOOL *stop) {
GBMethodSectionData *existingSection = [_sectionsByNames objectForKey:sourceSection.sectionName];
if (!existingSection) existingSection = [self registerSectionWithName:sourceSection.sectionName];
_registeringSection = existingSection;

[sourceSection.methods enumerateObjectsUsingBlock:^(GBMethodData *sourceMethod, NSUInteger idx, BOOL *stop) {
GBMethodData *existingMethod = [_methodsBySelectors objectForKey:sourceMethod.methodSelector];
if (existingMethod) {
if (existingMethod.methodType == sourceMethod.methodType) [existingMethod mergeDataFromObject:sourceMethod];
[newMethods enumerateObjectsUsingBlock:^(GBMethodData *sourceMethod, NSUInteger idx, BOOL *stop) {
if ([sourceSection.methods containsObject:sourceMethod]) {
GBMethodSectionData *existingSection = [_sectionsByNames objectForKey:sourceSection.sectionName];
if (!existingSection) existingSection = [self registerSectionWithName:sourceSection.sectionName];
_registeringSection = existingSection;
[self registerMethod:sourceMethod];
return;
}
[self registerMethod:sourceMethod];
}];
}];
_registeringSection = previousSection;
Expand Down
37 changes: 37 additions & 0 deletions Testing/GBMethodsProviderTesting.m
Expand Up @@ -439,6 +439,43 @@ - (void)testMergeDataFromObjectsProvider_shouldPreserveCurrentSectionForNewMetho
assertThat([[section.methods objectAtIndex:0] methodSelector], is(@"m2:"));
}

- (void)testMergeDataFromObjectsProvider_shouldUseOriginalSectionForExistingMethodsEvenIfFoundInDifferentSection {
// setup
GBMethodsProvider *original = [[GBMethodsProvider alloc] initWithParentObject:self];
[original registerSectionWithName:@"Section1"];
[original registerMethod:[GBTestObjectsRegistry instanceMethodWithNames:@"m1", nil]];
GBMethodsProvider *source = [[GBMethodsProvider alloc] initWithParentObject:self];
[source registerSectionWithName:@"Section2"];
[source registerMethod:[GBTestObjectsRegistry instanceMethodWithNames:@"m1", nil]];
// execute
[original mergeDataFromMethodsProvider:source];
// verify
NSArray *sections = [original sections];
assertThatInteger([sections count], equalToInteger(1));
GBMethodSectionData *section = [sections objectAtIndex:0];
assertThat([section sectionName], is(@"Section1"));
assertThatInteger([section.methods count], equalToInteger(1));
assertThat([[section.methods objectAtIndex:0] methodSelector], is(@"m1:"));
}

- (void)testMergeDataFromObjectsProvider_shouldUseOriginalSectionForExistingMethodsFromDefaultSection {
// setup
GBMethodsProvider *original = [[GBMethodsProvider alloc] initWithParentObject:self];
[original registerSectionWithName:@"Section1"];
[original registerMethod:[GBTestObjectsRegistry instanceMethodWithNames:@"m1", nil]];
GBMethodsProvider *source = [[GBMethodsProvider alloc] initWithParentObject:self];
[source registerMethod:[GBTestObjectsRegistry instanceMethodWithNames:@"m1", nil]];
// execute
[original mergeDataFromMethodsProvider:source];
// verify
NSArray *sections = [original sections];
assertThatInteger([sections count], equalToInteger(1));
GBMethodSectionData *section = [sections objectAtIndex:0];
assertThat([section sectionName], is(@"Section1"));
assertThatInteger([section.methods count], equalToInteger(1));
assertThat([[section.methods objectAtIndex:0] methodSelector], is(@"m1:"));
}

#pragma mark Unregistering handling

- (void)testUnregisterMethod_shouldRemoveMethodFromMethods {
Expand Down

0 comments on commit a0ed655

Please sign in to comment.