Permalink
Browse files

issue #206 - Rework support for Hamcrest matchers using a generic mec…

…hanism instead
  • Loading branch information...
1 parent 3c5d93c commit 0080ba57af184c881d2036f23c4698fc71158257 @allending committed Jan 31, 2013
@@ -6,7 +6,7 @@
#import "KWContainMatcher.h"
#import "KWFormatter.h"
-#import "KWHamrestMatchingAdditions.h"
+#import "KWGenericMatchingAdditions.h"
@interface KWContainMatcher()
@@ -0,0 +1,17 @@
+//
+// KWGenericMatcher.h
+// Kiwi
+//
+// Created by Allen Ding on 1/31/13.
+// Copyright (c) 2013 Allen Ding. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface KWGenericMatchEvaluator : NSObject
+
++ (BOOL)isGenericMatcher:(id)object;
+
++ (BOOL)genericMatcher:(id)matcher matches:(id)object;
+
+@end
@@ -0,0 +1,67 @@
+//
+// KWGenericMatcher.m
+// Kiwi
+//
+// Created by Allen Ding on 1/31/13.
+// Copyright (c) 2013 Allen Ding. All rights reserved.
+//
+
+#import "KWGenericMatchEvaluator.h"
+#import "KWStringUtilities.h"
+#import "KWObjCUtilities.h"
+#import <objc/runtime.h>
+
+@implementation KWGenericMatchEvaluator
+
+// Returns true only if the object has a method with the signature "- (void)matches:(id)object"
++ (BOOL)isGenericMatcher:(id)object
+{
+ Class theClass = object_getClass(object);
+
+ if (theClass == NULL) {
+ return NO;
+ }
+
+ Method method = class_getInstanceMethod(theClass, @selector(matches:));
+
+ if (method == NULL) {
+ return NO;
+ }
+
+ const char *cEncoding = method_getTypeEncoding(method);
+
+ if (cEncoding == NULL) {
+ return NO;
+ }
+
+ NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:cEncoding];
+
+ if (!KWObjCTypeEqualToObjCType(@encode(BOOL), [signature methodReturnType])) {
+ return NO;
+ }
+
+ if ([signature numberOfArguments] != 3) {
+ return NO;
+ }
+
+ if (!KWObjCTypeEqualToObjCType(@encode(id), [signature getArgumentTypeAtIndex:2])) {
+ return NO;
+ }
+
+ return YES;
+}
+
++ (BOOL)genericMatcher:(id)matcher matches:(id)object
+{
+ NSString *targetEncoding = KWEncodingWithObjCTypes(@encode(BOOL), @encode(id), @encode(SEL), @encode(id), nil);
+ NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:[targetEncoding UTF8String]];
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+ [invocation setSelector:@selector(matches:)];
+ [invocation setArgument:&object atIndex:2];
+ [invocation invokeWithTarget:matcher];
+ BOOL result = NO;
+ [invocation getReturnValue:&result];
+ return result;
+}
+
+@end
@@ -1,5 +1,5 @@
//
-// KWHamcrestMatcher.h
+// KWGenericMatcher.h
// Kiwi
//
// Created by Luke Redpath on 24/01/2011.
@@ -9,15 +9,11 @@
#import <Foundation/Foundation.h>
#import "KWMatcher.h"
-@protocol HCMatcher;
-
-@interface KWHamcrestMatcher : KWMatcher {
- id<HCMatcher> hamcrestMatcher;
-}
+@interface KWGenericMatcher : KWMatcher
#pragma mark -
#pragma mark Configuring Matchers
-- (void)match:(id<HCMatcher>)aMatcher;
+- (void)match:(id)aMatcher;
@end
@@ -1,24 +1,24 @@
//
-// KWHamcrestMatcher.m
+// KWGenericMatcher.m
// Kiwi
//
// Created by Luke Redpath on 24/01/2011.
// Copyright 2011 Allen Ding. All rights reserved.
//
-#import "KWHamcrestMatcher.h"
-#import "KWHCMatcher.h"
+#import "KWGenericMatcher.h"
+#import "KWGenericMatchEvaluator.h"
-@interface KWHamcrestMatcher ()
+@interface KWGenericMatcher ()
#pragma mark -
#pragma mark Properties
-@property (nonatomic, retain) id<HCMatcher> matcher;
+@property (nonatomic, retain) id matcher;
@end
-@implementation KWHamcrestMatcher
+@implementation KWGenericMatcher
@synthesize matcher;
@@ -32,7 +32,7 @@ - (void)dealloc
#pragma mark Matching
- (BOOL)evaluate {
- return [self.matcher matches:self.subject];
+ return [KWGenericMatchEvaluator genericMatcher:self.matcher matches:self.subject];
}
- (NSString *)failureMessageForShould {
@@ -54,7 +54,7 @@ + (NSArray *)matcherStrings {
#pragma mark -
#pragma mark Configuring Matchers
-- (void)match:(id<HCMatcher>)aMatcher;
+- (void)match:(id)aMatcher;
{
self.matcher = aMatcher;
}
@@ -8,28 +8,26 @@
#import <Foundation/Foundation.h>
-@interface NSObject (KiwiHamcrestAdditions)
+@interface NSObject (KiwiGenericMatchingAdditions)
- (BOOL)isEqualOrMatches:(id)object;
@end
-@protocol HCMatcher;
-
-@interface NSArray (KiwiHamcrestAdditions)
+@interface NSArray (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object;
-- (BOOL)containsObjectMatching:(id<HCMatcher>)matcher;
+- (BOOL)containsObjectMatching:(id)matcher;
@end
-@interface NSSet (KiwiHamcrestAdditions)
+@interface NSSet (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object;
@end
-@interface NSOrderedSet (KiwiHamcrestAdditions)
+@interface NSOrderedSet (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object;
@@ -6,37 +6,38 @@
// Copyright 2011 Allen Ding. All rights reserved.
//
-#import "KWHamrestMatchingAdditions.h"
-#import "KWHCMatcher.h"
+#import "KWGenericMatchingAdditions.h"
+#import "KWGenericMatcher.h"
+#import "KWGenericMatchEvaluator.h"
-@implementation NSObject (KiwiHamcrestAdditions)
+@implementation NSObject (KiwiGenericMatchingAdditions)
- (BOOL)isEqualOrMatches:(id)object
{
- if ([self conformsToProtocol:@protocol(HCMatcher)]) {
- return [(id<HCMatcher>)self matches:object];
+ if ([KWGenericMatchEvaluator isGenericMatcher:self]) {
+ return [KWGenericMatchEvaluator genericMatcher:self matches:object];
}
return [self isEqual:object];
}
@end
-@implementation NSArray (KiwiHamcrestAdditions)
+@implementation NSArray (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object
{
- if ([object conformsToProtocol:@protocol(HCMatcher)]) {
+ if ([KWGenericMatchEvaluator isGenericMatcher:object]) {
return [self containsObjectMatching:object];
}
return [self containsObject:object];
}
-- (BOOL)containsObjectMatching:(id<HCMatcher>)matcher
+- (BOOL)containsObjectMatching:(id)matcher
{
NSIndexSet *indexSet = [self indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
- BOOL matches = [matcher matches:obj];
+ BOOL matches = [KWGenericMatchEvaluator genericMatcher:matcher matches:obj];
if (matches) {
- *stop = YES;
+ *stop = YES;
}
return matches;
}];
@@ -46,28 +47,26 @@ - (BOOL)containsObjectMatching:(id<HCMatcher>)matcher
@end
-@implementation NSSet (KiwiHamcrestAdditions)
+@implementation NSSet (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object
{
- if ([object conformsToProtocol:@protocol(HCMatcher)]) {
+ if ([KWGenericMatchEvaluator isGenericMatcher:object]) {
return [[self allObjects] containsObjectMatching:object];
}
return [self containsObject:object];
}
@end
-@implementation NSOrderedSet (KiwiHamcrestAdditions)
+@implementation NSOrderedSet (KiwiGenericMatchingAdditions)
- (BOOL)containsObjectEqualToOrMatching:(id)object
{
- if ([object conformsToProtocol:@protocol(HCMatcher)]) {
+ if ([KWGenericMatchEvaluator isGenericMatcher:object]) {
return [[self array] containsObjectMatching:object];
}
return [self containsObject:object];
}
@end
-
-
View
@@ -1,12 +0,0 @@
-/**
- * This is a minimal version of HCMatcher from the Hamcrest library, purely
- * to support Hamcrest integration with Kiwi.
- *
- * The Hamcrest project can be found here: http://code.google.com/p/hamcrest/
- */
-
-#import <Foundation/Foundation.h>
-
-@protocol HCMatcher <NSObject>
-- (BOOL)matches:(id)item;
-@end
@@ -7,8 +7,8 @@
//
#import "KWHaveValueMatcher.h"
-#import "KWHamrestMatchingAdditions.h"
-#import "KWHCMatcher.h"
+#import "KWGenericMatchingAdditions.h"
+#import "KWGenericMatcher.h"
#import "KWFormatter.h"
@interface KWHaveValueMatcher()
View
@@ -11,7 +11,7 @@
#import "KWValue.h"
#import "NSInvocation+KiwiAdditions.h"
#import "NSMethodSignature+KiwiAdditions.h"
-#import "KWHCMatcher.h"
+#import "KWGenericMatchEvaluator.h"
#import "Kiwi.h"
@implementation KWMessagePattern
@@ -137,14 +137,14 @@ - (BOOL)argumentFiltersMatchInvocationArguments:(NSInvocation *)anInvocation {
continue;
}
- if ([argumentFilter conformsToProtocol:@protocol(HCMatcher)]) {
- id<HCMatcher> matcher = (id<HCMatcher>)argumentFilter;
+ if ([KWGenericMatchEvaluator isGenericMatcher:argumentFilter]) {
+ id matcher = argumentFilter;
if ([object isKindOfClass:[KWValue class]] && [object isNumeric]) {
NSNumber *number = [object numberValue];
- if (![matcher matches:number]) {
+ if (![KWGenericMatchEvaluator genericMatcher:matcher matches:number]) {
return NO;
}
- } else if (![matcher matches:object]) {
+ } else if (![KWGenericMatchEvaluator genericMatcher:matcher matches:object]) {
return NO;
}
} else if ([argumentFilter isEqual:[KWNull null]]) {
@@ -7,14 +7,14 @@
//
#import <Foundation/Foundation.h>
-#import "KWHCMatcher.h"
-@interface KWStringContainsMatcher : NSObject <HCMatcher> {
+@interface KWStringContainsMatcher : NSObject {
NSString *substring;
}
+ (id)matcherWithSubstring:(NSString *)aSubstring;
- (id)initWithSubstring:(NSString *)aSubstring;
+- (BOOL)matches:(id)object;
@end
@@ -7,9 +7,8 @@
//
#import <Foundation/Foundation.h>
-#import "KWHCMatcher.h"
-@interface KWStringPrefixMatcher : NSObject <HCMatcher> {
+@interface KWStringPrefixMatcher : NSObject {
NSString *prefix;
}
+ (id)matcherWithPrefix:(NSString *)aPrefix;
View
@@ -48,7 +48,7 @@ extern "C" {
#import "KWFailure.h"
#import "KWFormatter.h"
#import "KWFutureObject.h"
-#import "KWHamcrestMatcher.h"
+#import "KWGenericMatcher.h"
#import "KWHaveMatcher.h"
#import "KWHaveValueMatcher.h"
#import "KWInequalityMatcher.h"
Oops, something went wrong.

0 comments on commit 0080ba5

Please sign in to comment.