Browse files

Fixed methods and sections merging for GBMethodsProvider. Closes #73.

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...
1 parent 30d4e04 commit a0ed655705f6ac230d8cbf57627586c8577dc4a2 @tomaz committed Mar 1, 2011
Showing with 57 additions and 9 deletions.
  1. +20 −9 Model/GBMethodsProvider.m
  2. +37 −0 Testing/GBMethodsProviderTesting.m
View
29 Model/GBMethodsProvider.m
@@ -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;
View
37 Testing/GBMethodsProviderTesting.m
@@ -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 {

0 comments on commit a0ed655

Please sign in to comment.