{-# LANGUAGE QuasiQuotes #-}
module Objc (
objcTests,
objcRegressionTests
) where
import Test.Framework
import Test.Framework.Providers.HUnit
import Test.HUnit (Assertion, (@?=))
import Language.C.Quote.ObjC
objcTests :: Test
objcTests = testGroup "Objective-C"
[ testCase "Objective-C params" objcProp
, testCase "Objective-C property" objcDict
, testCase "Objective-C method parameters" objcParam
, testCase "Objective-C method definition" objcMethodDefinition
, testCase "Objective-C classmethod" objcArgumentCls
, testCase "Objective-C argument" objcArgument
, testCase "Objective-C arguments" objcArguments
, testCase "Objective-C varargument" objcVarArgument
, testCase "Objective-C literals" objcLits
]
where
objcDict :: Assertion
objcDict =
[cexp| @{$dictelems:(elems [("a","b"),("c", "d")])} |] @?= [cexp| @{@"a" : @"b",@"c": @"d"}|]
where
elems = map (\(k,v) -> [objcdictelem|$exp:(objcLit k) : $exp:(objcLit v)|] )
objcProp :: Assertion
objcProp =
[cedecl|
@interface Foo
- (void) foo;
$prop:propdec1
$props:propdec2
$prop:propdec3
@end
|]
@?=
[cedecl|
@interface Foo
- (void) foo;
@property (nonatomic, retain) int i;
@property (nonatomic, retain) float j;
@property (nonatomic, retain) char k;
@property (nonatomic) double l;
@end
|]
where
propdec n typ = [objcprop|@property ($propattrs:r) $ty:typ $id:n;|]
propdec' n typ = [objcprop|@property ($propattr:p) $ty:typ $id:n;|]
p = [objcpropattr|nonatomic|]
q = [objcpropattr|retain|]
r = [p,q]
propdec1 = propdec "i" [cty|int|]
propdec2 = map (\(n,t) -> propdec n t) [("j", [cty|float|]), ("k", [cty|char|])]
propdec3 = propdec' "l" [cty|double|]
objcParam :: Assertion
objcParam =
[cedecl|
@interface Foo
- (void) $methparams:paramNew ;
$methproto:val ;
@end
|]
@?=
[cedecl|
@interface Foo
- (void) foo:(int)str fo:(int)str1;
+ (int) test1:(int)str2;
@end
|]
where
paramNew1 = [objcmethparam|$id:("foo"):(int)str |]
paramNew2 = [objcmethparam|fo:(int)str1 |]
paramNew3 = [objcmethparam|test1:(int)str2 |]
paramNew = [paramNew1, paramNew2]
val = [objcmethproto|+ (int) $methparam:paramNew3|]
objcMethodDefinition :: Assertion
objcMethodDefinition =
[cedecl|
@implementation fooclass
$methdefs:(val)
$methdef:(val3)
@end
|]
@?=
[cedecl|
@implementation fooclass
+ (int) test1:(int)foo { }
- (char) test2:(char)bar { }
+ (float) test3:(double)baz { }
@end
|]
where
val3 = [objcmethdef|+ (float) $methparam:paramNew5 {} |]
paramNew5 = [objcmethparam|test3:(double)baz |]
val2 = [objcmethdef|+ (int) $methparam:paramNew3 {} |]
paramNew3 = [objcmethparam|test1:(int)foo |]
val1 = [objcmethdef|- (char) $methparam:paramNew4 {} |]
paramNew4 = [objcmethparam|test2:(char)bar |]
val = [val2, val1]
objcArgumentCls :: Assertion
objcArgumentCls =
[citem|[somename test];|] @?= [citem|[$recv:(k) $id:("test")];|]
where
k = [objcmethrecv|somename|]
objcArgument :: Assertion
objcArgument =
[citem|[$recv:(k) $kwarg:(p)];|] @?= [citem|[somename doSome:@"string"];|]
where
k = [objcmethrecv|somename|]
p = [objcarg|doSome:@"string"|]
objcArguments :: Assertion
objcArguments =
[citem|[$recv:(k) $kwargs:(r)];|]
@?= [citem|[somename doSome:@"string" doSomeMore:@"moreStrings"];|]
where
k = [objcmethrecv|somename|]
p = [objcarg|doSome:@"string"|]
q = [objcarg|doSomeMore:@"moreStrings"|]
r = [p,q]
objcVarArgument :: Assertion
objcVarArgument =
[citem|[$recv:(k) $kwarg:(r) $args:(p)];|]
@?= [citem|[NSString stringWithFormat:@"A string: %@, a float: %1.2f", @"string", 31415.9265];|]
where
k = [objcmethrecv|NSString|]
r = [objcarg|stringWithFormat:@"A string: %@, a float: %1.2f"|]
p = [a, b]
a = [cexp|@"string"|]
b = [cexp|31415.9265|]
objcLits :: Assertion
objcLits =
[cexp|@[$(objcLit "foo"), $(objcLit True), $(objcLit False), $(objcLit 'a'), nil]|]
@?= [cexp|@[@"foo", @YES, @NO, @'a', nil]|]
objcRegressionTests :: Test
objcRegressionTests = testGroup "Objective-C Regressions"
[ testCase "Issue #51" issue51 ]
where
issue51 :: Assertion
issue51 = [cunit|
@interface $id:prefixedClassName : NSObject
$ifdecls:ifaceDecls
@end
|]
@?= [cunit|
@interface dummyClass : NSObject
- (void) foo:(int)str fo:(int)str1;
+ (int) test1:(int)str2;
@end
|]
where
prefixedClassName :: String
prefixedClassName = "dummyClass"
ifaceDecls = [objcifdecls|
- (void) foo:(int)str fo:(int)str1;
+ (int) test1:(int)str2;
|]