diff --git a/Tests/EXTPassthroughTest.m b/Tests/EXTPassthroughTest.m index 896a23df..bd6ade92 100644 --- a/Tests/EXTPassthroughTest.m +++ b/Tests/EXTPassthroughTest.m @@ -10,67 +10,120 @@ #import "EXTPassthroughTest.h" @interface InnerClass : NSObject -@property (nonatomic, getter = isEnabled) BOOL enabled; - (void)voidMethod; - (int)methodWithString:(NSString *)str; - (int)methodWithString:(NSString *)str number:(NSNumber *)num; + +@property (nonatomic, getter = hasFlakyCrust, setter = topWithFlakyCrust:) BOOL flakyCrust; +@property (nonatomic, getter = isALaMode) BOOL aLaMode; +@property (strong, nonatomic, setter = assignFilling:, getter = whatIsTheFilling) NSString * filling; +@property (nonatomic) NSTimeInterval bakingTime; + @end @interface OuterClass : NSObject @property (nonatomic, strong) InnerClass *inner; + +@property (nonatomic, getter = hasFlakyCrust, setter = topWithFlakyCrust:) BOOL flakyCrust; +@property (nonatomic) BOOL aLaMode; +@property (strong, nonatomic) NSString * fruitType; + @end @interface OuterClass (DelegatedMethods) -@property (nonatomic, getter = isEnabled) BOOL enabled; - (void)renamedMethod; - (int)methodWithString:(NSString *)str; - (int)methodWithString:(NSString *)str number:(NSNumber *)num; @end +@interface OuterClass (DelegatedProperty) +@property (nonatomic) NSTimeInterval bakingTime; +@end + @implementation EXTPassthroughTest - (void)testPassthroughMethods { OuterClass *outer = [[OuterClass alloc] init]; STAssertNotNil(outer, @""); - + [outer renamedMethod]; STAssertEquals([outer methodWithString:@"foo"], 3, @""); STAssertEquals([outer methodWithString:@"foobar" number:@5], 11, @""); } -- (void)testPassthroughProperty { +- (void)testPassthroughPropertyCustomAccessors { OuterClass *outer = [[OuterClass alloc] init]; STAssertNotNil(outer, @""); - STAssertFalse(outer.enabled, @""); - STAssertFalse(outer.inner.enabled, @""); + STAssertFalse(outer.flakyCrust, @""); + STAssertFalse(outer.inner.flakyCrust, @""); + + outer.flakyCrust = YES; + STAssertTrue(outer.flakyCrust, @""); + STAssertTrue(outer.inner.flakyCrust, @""); +} - outer.enabled = YES; - STAssertTrue(outer.enabled, @""); - STAssertTrue(outer.inner.enabled, @""); +- (void)testPassthroughPropertySameBaseNameDifferentAccessors { + OuterClass *outer = [[OuterClass alloc] init]; + STAssertNotNil(outer, @""); + STAssertFalse(outer.aLaMode, @""); + STAssertFalse(outer.inner.aLaMode, @""); + + outer.aLaMode = YES; + STAssertTrue(outer.aLaMode, @""); + STAssertTrue(outer.inner.aLaMode, @""); } +- (void)testPassthroughPropertyDifferentNames { + OuterClass *outer = [[OuterClass alloc] init]; + STAssertNotNil(outer, @""); + STAssertEqualObjects(nil, outer.fruitType, @""); + STAssertEqualObjects(nil, outer.inner.filling, @""); + + outer.fruitType = @"Pear"; + STAssertEqualObjects(@"Pear", outer.fruitType, @""); + STAssertEqualObjects(@"Pear", outer.inner.filling, @""); +} + +- (void)testPassthroughPropertySameNames { + OuterClass *outer = [[OuterClass alloc] init]; + STAssertNotNil(outer, @""); + STAssertEquals(0.0, outer.bakingTime, @""); + STAssertEquals(0.0, outer.inner.bakingTime, @""); + + outer.bakingTime = 75.0; + STAssertEqualsWithAccuracy(75.0, outer.bakingTime, 0.5, @""); + STAssertEqualsWithAccuracy(75.0, outer.inner.bakingTime, 0.5, @""); +} + + @end @implementation OuterClass @passthrough(OuterClass, renamedMethod, self.inner, voidMethod); @passthrough(OuterClass, methodWithString:, self.inner); @passthrough(OuterClass, methodWithString:number:, [self inner]); -@passthrough(OuterClass, isEnabled, self.inner); -@passthrough(OuterClass, setEnabled:, self.inner); + +@passthrough_property(OuterClass, flakyCrust, self.inner); +@passthrough_property(OuterClass, fruitType, self.inner, filling); +@passthrough_property(OuterClass, aLaMode, self.inner, aLaMode); - (id)init { self = [super init]; if (!self) return nil; - + self.inner = [[InnerClass alloc] init]; return self; } @end +@implementation OuterClass (DelegatedProperty) +@passthrough_property(OuterClass, bakingTime, self.inner); +@end + @implementation InnerClass - (void)voidMethod { diff --git a/extobjc.xcodeproj/project.pbxproj b/extobjc.xcodeproj/project.pbxproj index 2e625504..618cc75d 100644 --- a/extobjc.xcodeproj/project.pbxproj +++ b/extobjc.xcodeproj/project.pbxproj @@ -7,6 +7,44 @@ objects = { /* Begin PBXBuildFile section */ + 030C01AF181D155B00C77CA9 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 030C01AB181D153400C77CA9 /* libffi.a */; }; + 030C01B0181D156200C77CA9 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 030C01AD181D153400C77CA9 /* libffi.a */; }; + 030C01E7181DADBA00C77CA9 /* EXTADT.m in Sources */ = {isa = PBXBuildFile; fileRef = D0EF9BFE15992F080066DFBC /* EXTADT.m */; }; + 030C01E8181DADBA00C77CA9 /* EXTAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0ED159BB43B00FB92FC /* EXTAnnotation.m */; }; + 030C01EA181DADBA00C77CA9 /* EXTBlockMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01C15950509007A8A1C /* EXTBlockMethod.m */; }; + 030C01EB181DADBA00C77CA9 /* EXTBlockTarget.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01E15950509007A8A1C /* EXTBlockTarget.m */; }; + 030C01EC181DADBA00C77CA9 /* EXTConcreteProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02015950509007A8A1C /* EXTConcreteProtocol.m */; }; + 030C01ED181DADBA00C77CA9 /* EXTDispatchObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02315950509007A8A1C /* EXTDispatchObject.m */; }; + 030C01EE181DADBA00C77CA9 /* EXTFinalMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02515950509007A8A1C /* EXTFinalMethod.m */; }; + 030C01EF181DADBA00C77CA9 /* EXTMaybe.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02815950509007A8A1C /* EXTMaybe.m */; }; + 030C01F0181DADBA00C77CA9 /* EXTMultimethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE93FD1596665D00F3AE1C /* EXTMultimethod.m */; }; + 030C01F1181DADBA00C77CA9 /* EXTMultiObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02B15950509007A8A1C /* EXTMultiObject.m */; }; + 030C01F2181DADBA00C77CA9 /* EXTNil.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02D15950509007A8A1C /* EXTNil.m */; }; + 030C01F3181DADBA00C77CA9 /* EXTPrivateMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03115950509007A8A1C /* EXTPrivateMethod.m */; }; + 030C01F4181DADBA00C77CA9 /* EXTProtocolCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03315950509007A8A1C /* EXTProtocolCategory.m */; }; + 030C01F5181DADBA00C77CA9 /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03515950509007A8A1C /* EXTRuntimeExtensions.m */; }; + 030C01F6181DADBA00C77CA9 /* EXTSafeCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03715950509007A8A1C /* EXTSafeCategory.m */; }; + 030C01F7181DADBA00C77CA9 /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03915950509007A8A1C /* EXTScope.m */; }; + 030C01F8181DADBA00C77CA9 /* EXTSelectorChecking.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2FC159A459700A5F6A4 /* EXTSelectorChecking.m */; }; + 030C01F9181DADBA00C77CA9 /* EXTVarargs.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03D15950509007A8A1C /* EXTVarargs.m */; }; + 030C01FA181DADCF00C77CA9 /* EXTADT.m in Sources */ = {isa = PBXBuildFile; fileRef = D0EF9BFE15992F080066DFBC /* EXTADT.m */; }; + 030C01FB181DADCF00C77CA9 /* EXTAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0ED159BB43B00FB92FC /* EXTAnnotation.m */; }; + 030C01FD181DADCF00C77CA9 /* EXTBlockMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01C15950509007A8A1C /* EXTBlockMethod.m */; }; + 030C01FE181DADCF00C77CA9 /* EXTBlockTarget.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01E15950509007A8A1C /* EXTBlockTarget.m */; }; + 030C01FF181DADCF00C77CA9 /* EXTConcreteProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02015950509007A8A1C /* EXTConcreteProtocol.m */; }; + 030C0200181DADCF00C77CA9 /* EXTDispatchObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02315950509007A8A1C /* EXTDispatchObject.m */; }; + 030C0201181DADCF00C77CA9 /* EXTFinalMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02515950509007A8A1C /* EXTFinalMethod.m */; }; + 030C0202181DADCF00C77CA9 /* EXTMaybe.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02815950509007A8A1C /* EXTMaybe.m */; }; + 030C0203181DADCF00C77CA9 /* EXTMultimethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE93FD1596665D00F3AE1C /* EXTMultimethod.m */; }; + 030C0204181DADCF00C77CA9 /* EXTMultiObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02B15950509007A8A1C /* EXTMultiObject.m */; }; + 030C0205181DADCF00C77CA9 /* EXTNil.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02D15950509007A8A1C /* EXTNil.m */; }; + 030C0206181DADCF00C77CA9 /* EXTPrivateMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03115950509007A8A1C /* EXTPrivateMethod.m */; }; + 030C0207181DADCF00C77CA9 /* EXTProtocolCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03315950509007A8A1C /* EXTProtocolCategory.m */; }; + 030C0208181DADCF00C77CA9 /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03515950509007A8A1C /* EXTRuntimeExtensions.m */; }; + 030C0209181DADCF00C77CA9 /* EXTSafeCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03715950509007A8A1C /* EXTSafeCategory.m */; }; + 030C020A181DADCF00C77CA9 /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03915950509007A8A1C /* EXTScope.m */; }; + 030C020B181DADCF00C77CA9 /* EXTSelectorChecking.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2FC159A459700A5F6A4 /* EXTSelectorChecking.m */; }; + 030C020C181DADCF00C77CA9 /* EXTVarargs.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03D15950509007A8A1C /* EXTVarargs.m */; }; 876EE9D6170B13C000AB73BB /* EXTObjectiveCppCompileTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 876EE9D5170B13C000AB73BB /* EXTObjectiveCppCompileTest.mm */; }; 876EE9D7170B13C000AB73BB /* EXTObjectiveCppCompileTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 876EE9D5170B13C000AB73BB /* EXTObjectiveCppCompileTest.mm */; }; D002DAF813656CDF005348A5 /* EXTNilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D002DAF713656CDF005348A5 /* EXTNilTest.m */; }; @@ -15,80 +53,48 @@ D003EEF015924CF000410411 /* EXTVarargsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D003EEEE15924CF000410411 /* EXTVarargsTest.m */; }; D005F04315950509007A8A1C /* EXTADT.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01815950509007A8A1C /* EXTADT.h */; }; D005F04415950509007A8A1C /* EXTADT.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01815950509007A8A1C /* EXTADT.h */; }; - D005F04515950509007A8A1C /* EXTAspect.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01915950509007A8A1C /* EXTAspect.h */; }; - D005F04615950509007A8A1C /* EXTAspect.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01915950509007A8A1C /* EXTAspect.h */; }; - D005F04715950509007A8A1C /* EXTAspect.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01A15950509007A8A1C /* EXTAspect.m */; }; - D005F04815950509007A8A1C /* EXTAspect.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01A15950509007A8A1C /* EXTAspect.m */; }; D005F04915950509007A8A1C /* EXTBlockMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01B15950509007A8A1C /* EXTBlockMethod.h */; }; D005F04A15950509007A8A1C /* EXTBlockMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01B15950509007A8A1C /* EXTBlockMethod.h */; }; - D005F04B15950509007A8A1C /* EXTBlockMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01C15950509007A8A1C /* EXTBlockMethod.m */; }; - D005F04C15950509007A8A1C /* EXTBlockMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01C15950509007A8A1C /* EXTBlockMethod.m */; }; D005F04D15950509007A8A1C /* EXTBlockTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01D15950509007A8A1C /* EXTBlockTarget.h */; }; D005F04E15950509007A8A1C /* EXTBlockTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01D15950509007A8A1C /* EXTBlockTarget.h */; }; - D005F04F15950509007A8A1C /* EXTBlockTarget.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01E15950509007A8A1C /* EXTBlockTarget.m */; }; - D005F05015950509007A8A1C /* EXTBlockTarget.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F01E15950509007A8A1C /* EXTBlockTarget.m */; }; D005F05115950509007A8A1C /* EXTConcreteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01F15950509007A8A1C /* EXTConcreteProtocol.h */; }; D005F05215950509007A8A1C /* EXTConcreteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F01F15950509007A8A1C /* EXTConcreteProtocol.h */; }; - D005F05315950509007A8A1C /* EXTConcreteProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02015950509007A8A1C /* EXTConcreteProtocol.m */; }; - D005F05415950509007A8A1C /* EXTConcreteProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02015950509007A8A1C /* EXTConcreteProtocol.m */; }; D005F05515950509007A8A1C /* EXTCoroutine.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02115950509007A8A1C /* EXTCoroutine.h */; }; D005F05615950509007A8A1C /* EXTCoroutine.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02115950509007A8A1C /* EXTCoroutine.h */; }; D005F05715950509007A8A1C /* EXTDispatchObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02215950509007A8A1C /* EXTDispatchObject.h */; }; D005F05815950509007A8A1C /* EXTDispatchObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02215950509007A8A1C /* EXTDispatchObject.h */; }; - D005F05915950509007A8A1C /* EXTDispatchObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02315950509007A8A1C /* EXTDispatchObject.m */; }; - D005F05A15950509007A8A1C /* EXTDispatchObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02315950509007A8A1C /* EXTDispatchObject.m */; }; D005F05B15950509007A8A1C /* EXTFinalMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02415950509007A8A1C /* EXTFinalMethod.h */; }; D005F05C15950509007A8A1C /* EXTFinalMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02415950509007A8A1C /* EXTFinalMethod.h */; }; - D005F05D15950509007A8A1C /* EXTFinalMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02515950509007A8A1C /* EXTFinalMethod.m */; }; - D005F05E15950509007A8A1C /* EXTFinalMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02515950509007A8A1C /* EXTFinalMethod.m */; }; D005F05F15950509007A8A1C /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02615950509007A8A1C /* EXTKeyPathCoding.h */; }; D005F06015950509007A8A1C /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02615950509007A8A1C /* EXTKeyPathCoding.h */; }; D005F06115950509007A8A1C /* EXTMaybe.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02715950509007A8A1C /* EXTMaybe.h */; }; D005F06215950509007A8A1C /* EXTMaybe.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02715950509007A8A1C /* EXTMaybe.h */; }; - D005F06315950509007A8A1C /* EXTMaybe.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02815950509007A8A1C /* EXTMaybe.m */; }; - D005F06415950509007A8A1C /* EXTMaybe.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02815950509007A8A1C /* EXTMaybe.m */; }; D005F06515950509007A8A1C /* EXTMixin.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02915950509007A8A1C /* EXTMixin.h */; }; D005F06615950509007A8A1C /* EXTMixin.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02915950509007A8A1C /* EXTMixin.h */; }; D005F06715950509007A8A1C /* EXTMultiObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02A15950509007A8A1C /* EXTMultiObject.h */; }; D005F06815950509007A8A1C /* EXTMultiObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02A15950509007A8A1C /* EXTMultiObject.h */; }; - D005F06915950509007A8A1C /* EXTMultiObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02B15950509007A8A1C /* EXTMultiObject.m */; }; - D005F06A15950509007A8A1C /* EXTMultiObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02B15950509007A8A1C /* EXTMultiObject.m */; }; D005F06B15950509007A8A1C /* EXTNil.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02C15950509007A8A1C /* EXTNil.h */; }; D005F06C15950509007A8A1C /* EXTNil.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02C15950509007A8A1C /* EXTNil.h */; }; - D005F06D15950509007A8A1C /* EXTNil.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02D15950509007A8A1C /* EXTNil.m */; }; - D005F06E15950509007A8A1C /* EXTNil.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F02D15950509007A8A1C /* EXTNil.m */; }; D005F06F15950509007A8A1C /* extobjc_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D005F02E15950509007A8A1C /* extobjc_Prefix.pch */; }; D005F07015950509007A8A1C /* extobjc_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = D005F02E15950509007A8A1C /* extobjc_Prefix.pch */; }; D005F07115950509007A8A1C /* extobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02F15950509007A8A1C /* extobjc.h */; }; D005F07215950509007A8A1C /* extobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F02F15950509007A8A1C /* extobjc.h */; }; D005F07315950509007A8A1C /* EXTPrivateMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03015950509007A8A1C /* EXTPrivateMethod.h */; }; D005F07415950509007A8A1C /* EXTPrivateMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03015950509007A8A1C /* EXTPrivateMethod.h */; }; - D005F07515950509007A8A1C /* EXTPrivateMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03115950509007A8A1C /* EXTPrivateMethod.m */; }; - D005F07615950509007A8A1C /* EXTPrivateMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03115950509007A8A1C /* EXTPrivateMethod.m */; }; D005F07715950509007A8A1C /* EXTProtocolCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03215950509007A8A1C /* EXTProtocolCategory.h */; }; D005F07815950509007A8A1C /* EXTProtocolCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03215950509007A8A1C /* EXTProtocolCategory.h */; }; - D005F07915950509007A8A1C /* EXTProtocolCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03315950509007A8A1C /* EXTProtocolCategory.m */; }; - D005F07A15950509007A8A1C /* EXTProtocolCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03315950509007A8A1C /* EXTProtocolCategory.m */; }; D005F07B15950509007A8A1C /* EXTRuntimeExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03415950509007A8A1C /* EXTRuntimeExtensions.h */; }; D005F07C15950509007A8A1C /* EXTRuntimeExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03415950509007A8A1C /* EXTRuntimeExtensions.h */; }; - D005F07D15950509007A8A1C /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03515950509007A8A1C /* EXTRuntimeExtensions.m */; }; - D005F07E15950509007A8A1C /* EXTRuntimeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03515950509007A8A1C /* EXTRuntimeExtensions.m */; }; D005F07F15950509007A8A1C /* EXTSafeCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03615950509007A8A1C /* EXTSafeCategory.h */; }; D005F08015950509007A8A1C /* EXTSafeCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03615950509007A8A1C /* EXTSafeCategory.h */; }; - D005F08115950509007A8A1C /* EXTSafeCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03715950509007A8A1C /* EXTSafeCategory.m */; }; - D005F08215950509007A8A1C /* EXTSafeCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03715950509007A8A1C /* EXTSafeCategory.m */; }; D005F08315950509007A8A1C /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03815950509007A8A1C /* EXTScope.h */; }; D005F08415950509007A8A1C /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03815950509007A8A1C /* EXTScope.h */; }; - D005F08515950509007A8A1C /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03915950509007A8A1C /* EXTScope.m */; }; - D005F08615950509007A8A1C /* EXTScope.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03915950509007A8A1C /* EXTScope.m */; }; D005F08715950509007A8A1C /* EXTSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03A15950509007A8A1C /* EXTSwizzle.h */; }; D005F08815950509007A8A1C /* EXTSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03A15950509007A8A1C /* EXTSwizzle.h */; }; D005F08915950509007A8A1C /* EXTTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03B15950509007A8A1C /* EXTTuple.h */; }; D005F08A15950509007A8A1C /* EXTTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03B15950509007A8A1C /* EXTTuple.h */; }; D005F08B15950509007A8A1C /* EXTVarargs.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03C15950509007A8A1C /* EXTVarargs.h */; }; D005F08C15950509007A8A1C /* EXTVarargs.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03C15950509007A8A1C /* EXTVarargs.h */; }; - D005F08D15950509007A8A1C /* EXTVarargs.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03D15950509007A8A1C /* EXTVarargs.m */; }; - D005F08E15950509007A8A1C /* EXTVarargs.m in Sources */ = {isa = PBXBuildFile; fileRef = D005F03D15950509007A8A1C /* EXTVarargs.m */; }; D005F08F15950509007A8A1C /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03E15950509007A8A1C /* metamacros.h */; }; D005F09015950509007A8A1C /* metamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03E15950509007A8A1C /* metamacros.h */; }; D005F09115950509007A8A1C /* NSInvocation+EXT.h in Headers */ = {isa = PBXBuildFile; fileRef = D005F03F15950509007A8A1C /* NSInvocation+EXT.h */; }; @@ -103,14 +109,10 @@ D033765E131E53DB0039ACFD /* EXTPrivateMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D033765C131E53DB0039ACFD /* EXTPrivateMethodTest.m */; }; D0337667131E54960039ACFD /* EXTFinalMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0337666131E54960039ACFD /* EXTFinalMethodTest.m */; }; D0337668131E54960039ACFD /* EXTFinalMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0337666131E54960039ACFD /* EXTFinalMethodTest.m */; }; - D035A5BB148022B9006C1001 /* EXTAspectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D035A5BA148022B9006C1001 /* EXTAspectTest.m */; }; - D035A5BC148022B9006C1001 /* EXTAspectTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D035A5BA148022B9006C1001 /* EXTAspectTest.m */; }; D03EC9A3138A25F100559080 /* EXTCoroutineTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D03EC9A2138A25F100559080 /* EXTCoroutineTest.m */; }; D03EC9A4138A25F100559080 /* EXTCoroutineTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D03EC9A2138A25F100559080 /* EXTCoroutineTest.m */; }; D05F5BF71335E43F00A34927 /* EXTBlockMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D05F5BF61335E43F00A34927 /* EXTBlockMethodTest.m */; }; D05F5BF81335E43F00A34927 /* EXTBlockMethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D05F5BF61335E43F00A34927 /* EXTBlockMethodTest.m */; }; - D06674E715990AB8001537C5 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D06674E215990AAB001537C5 /* libffi.a */; }; - D06674E815990ABD001537C5 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D06674E015990AAB001537C5 /* libffi.a */; }; D0737D9414CB9438005BF183 /* EXTMaybeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0737D9314CB9438005BF183 /* EXTMaybeTest.m */; }; D0737D9514CB9438005BF183 /* EXTMaybeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0737D9314CB9438005BF183 /* EXTMaybeTest.m */; }; D07F83B2135D50E9008B9D6D /* EXTBlockTargetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D07F83B1135D50E9008B9D6D /* EXTBlockTargetTest.m */; }; @@ -123,8 +125,6 @@ D09FB2F7159A41C400A5F6A4 /* EXTSelectorChecking.h in Headers */ = {isa = PBXBuildFile; fileRef = D09FB2F5159A41C400A5F6A4 /* EXTSelectorChecking.h */; }; D09FB2FA159A41D100A5F6A4 /* EXTSelectorCheckingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2F9159A41D100A5F6A4 /* EXTSelectorCheckingTest.m */; }; D09FB2FB159A41D100A5F6A4 /* EXTSelectorCheckingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2F9159A41D100A5F6A4 /* EXTSelectorCheckingTest.m */; }; - D09FB2FD159A459700A5F6A4 /* EXTSelectorChecking.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2FC159A459700A5F6A4 /* EXTSelectorChecking.m */; }; - D09FB2FE159A459700A5F6A4 /* EXTSelectorChecking.m in Sources */ = {isa = PBXBuildFile; fileRef = D09FB2FC159A459700A5F6A4 /* EXTSelectorChecking.m */; }; D0A8B04F128A42F4004AACE0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; D0A8B188128A4303004AACE0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0A8B187128A4303004AACE0 /* Foundation.framework */; }; D0A8B30E128A4B56004AACE0 /* EXTSwizzleTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0A8B30D128A4B56004AACE0 /* EXTSwizzleTest.m */; }; @@ -143,8 +143,6 @@ D0D1F93515A396F7002E2387 /* EXTPassthroughTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0D1F93315A396F7002E2387 /* EXTPassthroughTest.m */; }; D0E6A0EE159BB43B00FB92FC /* EXTAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = D0E6A0EC159BB43B00FB92FC /* EXTAnnotation.h */; }; D0E6A0EF159BB43B00FB92FC /* EXTAnnotation.h in Headers */ = {isa = PBXBuildFile; fileRef = D0E6A0EC159BB43B00FB92FC /* EXTAnnotation.h */; }; - D0E6A0F0159BB43B00FB92FC /* EXTAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0ED159BB43B00FB92FC /* EXTAnnotation.m */; }; - D0E6A0F1159BB43B00FB92FC /* EXTAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0ED159BB43B00FB92FC /* EXTAnnotation.m */; }; D0E6A0F4159BB46D00FB92FC /* EXTAnnotationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0F3159BB46D00FB92FC /* EXTAnnotationTest.m */; }; D0E6A0F5159BB46D00FB92FC /* EXTAnnotationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E6A0F3159BB46D00FB92FC /* EXTAnnotationTest.m */; }; D0E7E85A128F81FA00FE0263 /* EXTSafeCategoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E7E83A128F7F2E00FE0263 /* EXTSafeCategoryTest.m */; }; @@ -152,49 +150,31 @@ D0E7E8CA128F8D1400FE0263 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0E7E8C9128F8D1400FE0263 /* CoreFoundation.framework */; }; D0E7E909128F8DD200FE0263 /* EXTProtocolCategoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E7E908128F8DD200FE0263 /* EXTProtocolCategoryTest.m */; }; D0E7E90A128F8DD200FE0263 /* EXTProtocolCategoryTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0E7E908128F8DD200FE0263 /* EXTProtocolCategoryTest.m */; }; - D0EF9BFF15992F080066DFBC /* EXTADT.m in Sources */ = {isa = PBXBuildFile; fileRef = D0EF9BFE15992F080066DFBC /* EXTADT.m */; }; - D0EF9C0015992F080066DFBC /* EXTADT.m in Sources */ = {isa = PBXBuildFile; fileRef = D0EF9BFE15992F080066DFBC /* EXTADT.m */; }; D0FBB1DB15F6897D002281B9 /* EXTSynthesizeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FBB1DA15F6897D002281B9 /* EXTSynthesizeTest.m */; }; D0FBB1DC15F6897D002281B9 /* EXTSynthesizeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FBB1DA15F6897D002281B9 /* EXTSynthesizeTest.m */; }; D0FD397413243A31009300A7 /* EXTRuntimeExtensionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FD397313243A31009300A7 /* EXTRuntimeExtensionsTest.m */; }; D0FD397513243A31009300A7 /* EXTRuntimeExtensionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FD397313243A31009300A7 /* EXTRuntimeExtensionsTest.m */; }; D0FE93FE1596665D00F3AE1C /* EXTMultimethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FE93FC1596665D00F3AE1C /* EXTMultimethod.h */; }; D0FE93FF1596665D00F3AE1C /* EXTMultimethod.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FE93FC1596665D00F3AE1C /* EXTMultimethod.h */; }; - D0FE94001596665D00F3AE1C /* EXTMultimethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE93FD1596665D00F3AE1C /* EXTMultimethod.m */; }; - D0FE94011596665D00F3AE1C /* EXTMultimethod.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE93FD1596665D00F3AE1C /* EXTMultimethod.m */; }; D0FE94041596668400F3AE1C /* EXTMultimethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE94031596668400F3AE1C /* EXTMultimethodTest.m */; }; D0FE94051596668400F3AE1C /* EXTMultimethodTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0FE94031596668400F3AE1C /* EXTMultimethodTest.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - D06674DF15990AAB001537C5 /* PBXContainerItemProxy */ = { + 030C01AA181D153400C77CA9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D06674D715990AAB001537C5 /* libffi.xcodeproj */; + containerPortal = 030C01A5181D153400C77CA9 /* libffi.xcodeproj */; proxyType = 2; remoteGlobalIDString = F6F980BA147386130008F121; remoteInfo = "libffi iOS"; }; - D06674E115990AAB001537C5 /* PBXContainerItemProxy */ = { + 030C01AC181D153400C77CA9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = D06674D715990AAB001537C5 /* libffi.xcodeproj */; + containerPortal = 030C01A5181D153400C77CA9 /* libffi.xcodeproj */; proxyType = 2; remoteGlobalIDString = 6C43CB3D1534E9D100162364; remoteInfo = "libffi OS X"; }; - D06674E315990AB1001537C5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D06674D715990AAB001537C5 /* libffi.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = F6F980B9147386130008F121; - remoteInfo = "libffi iOS"; - }; - D06674E515990AB4001537C5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = D06674D715990AAB001537C5 /* libffi.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 6C43CB3C1534E9D100162364; - remoteInfo = "libffi OS X"; - }; D0CFB603128A8EB6006DC377 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; @@ -212,6 +192,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 030C01A5181D153400C77CA9 /* libffi.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libffi.xcodeproj; path = ../libffi/libffi.xcodeproj; sourceTree = ""; }; 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 876EE9D4170B13C000AB73BB /* EXTObjectiveCppCompileTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTObjectiveCppCompileTest.h; sourceTree = ""; }; 876EE9D5170B13C000AB73BB /* EXTObjectiveCppCompileTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EXTObjectiveCppCompileTest.mm; sourceTree = ""; }; @@ -220,8 +201,6 @@ D003EEED15924CF000410411 /* EXTVarargsTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTVarargsTest.h; sourceTree = ""; }; D003EEEE15924CF000410411 /* EXTVarargsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTVarargsTest.m; sourceTree = ""; }; D005F01815950509007A8A1C /* EXTADT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTADT.h; sourceTree = ""; }; - D005F01915950509007A8A1C /* EXTAspect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTAspect.h; sourceTree = ""; }; - D005F01A15950509007A8A1C /* EXTAspect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTAspect.m; sourceTree = ""; }; D005F01B15950509007A8A1C /* EXTBlockMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlockMethod.h; sourceTree = ""; }; D005F01C15950509007A8A1C /* EXTBlockMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTBlockMethod.m; sourceTree = ""; }; D005F01D15950509007A8A1C /* EXTBlockTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlockTarget.h; sourceTree = ""; }; @@ -266,13 +245,10 @@ D033765C131E53DB0039ACFD /* EXTPrivateMethodTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTPrivateMethodTest.m; sourceTree = ""; }; D0337665131E54960039ACFD /* EXTFinalMethodTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTFinalMethodTest.h; sourceTree = ""; }; D0337666131E54960039ACFD /* EXTFinalMethodTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTFinalMethodTest.m; sourceTree = ""; }; - D035A5B9148022B9006C1001 /* EXTAspectTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTAspectTest.h; sourceTree = ""; }; - D035A5BA148022B9006C1001 /* EXTAspectTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTAspectTest.m; sourceTree = ""; }; D03EC9A1138A25F100559080 /* EXTCoroutineTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTCoroutineTest.h; sourceTree = ""; }; D03EC9A2138A25F100559080 /* EXTCoroutineTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTCoroutineTest.m; sourceTree = ""; }; D05F5BF51335E43F00A34927 /* EXTBlockMethodTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlockMethodTest.h; sourceTree = ""; }; D05F5BF61335E43F00A34927 /* EXTBlockMethodTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTBlockMethodTest.m; sourceTree = ""; }; - D06674D715990AAB001537C5 /* libffi.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libffi.xcodeproj; path = libffi/libffi.xcodeproj; sourceTree = ""; }; D0737D9214CB9438005BF183 /* EXTMaybeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTMaybeTest.h; sourceTree = ""; }; D0737D9314CB9438005BF183 /* EXTMaybeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTMaybeTest.m; sourceTree = ""; }; D07F83B0135D50E9008B9D6D /* EXTBlockTargetTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlockTargetTest.h; sourceTree = ""; }; @@ -344,7 +320,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D06674E815990ABD001537C5 /* libffi.a in Frameworks */, + 030C01AF181D155B00C77CA9 /* libffi.a in Frameworks */, D0A8B188128A4303004AACE0 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -370,7 +346,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D06674E715990AB8001537C5 /* libffi.a in Frameworks */, + 030C01B0181D156200C77CA9 /* libffi.a in Frameworks */, D0A8B04F128A42F4004AACE0 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -378,6 +354,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 030C01A6181D153400C77CA9 /* Products */ = { + isa = PBXGroup; + children = ( + 030C01AB181D153400C77CA9 /* libffi.a */, + 030C01AD181D153400C77CA9 /* libffi.a */, + ); + name = Products; + sourceTree = ""; + }; 034768DFFF38A50411DB9C8B /* Products */ = { isa = PBXGroup; children = ( @@ -404,7 +389,7 @@ 0867D69AFE84028FC02AAC07 /* Frameworks */ = { isa = PBXGroup; children = ( - D06674D715990AAB001537C5 /* libffi.xcodeproj */, + 030C01A5181D153400C77CA9 /* libffi.xcodeproj */, D0A8B20B128A430D004AACE0 /* iOS */, D0A8B20A128A430A004AACE0 /* Mac OS X */, ); @@ -428,8 +413,6 @@ D0EF9BFE15992F080066DFBC /* EXTADT.m */, D0E6A0EC159BB43B00FB92FC /* EXTAnnotation.h */, D0E6A0ED159BB43B00FB92FC /* EXTAnnotation.m */, - D005F01915950509007A8A1C /* EXTAspect.h */, - D005F01A15950509007A8A1C /* EXTAspect.m */, D005F01B15950509007A8A1C /* EXTBlockMethod.h */, D005F01C15950509007A8A1C /* EXTBlockMethod.m */, D005F01D15950509007A8A1C /* EXTBlockTarget.h */, @@ -494,15 +477,6 @@ name = "Other Sources"; sourceTree = ""; }; - D06674D815990AAB001537C5 /* Products */ = { - isa = PBXGroup; - children = ( - D06674E015990AAB001537C5 /* libffi.a */, - D06674E215990AAB001537C5 /* libffi.a */, - ); - name = Products; - sourceTree = ""; - }; D0919C4B146F99B900D680C9 /* Configuration */ = { isa = PBXGroup; children = ( @@ -589,8 +563,6 @@ D088C7F41591377000C70CE2 /* EXTADTTest.m */, D0E6A0F2159BB46D00FB92FC /* EXTAnnotationTest.h */, D0E6A0F3159BB46D00FB92FC /* EXTAnnotationTest.m */, - D035A5B9148022B9006C1001 /* EXTAspectTest.h */, - D035A5BA148022B9006C1001 /* EXTAspectTest.m */, D05F5BF51335E43F00A34927 /* EXTBlockMethodTest.h */, D05F5BF61335E43F00A34927 /* EXTBlockMethodTest.m */, D07F83B0135D50E9008B9D6D /* EXTBlockTargetTest.h */, @@ -647,7 +619,6 @@ buildActionMask = 2147483647; files = ( D005F04415950509007A8A1C /* EXTADT.h in Headers */, - D005F04615950509007A8A1C /* EXTAspect.h in Headers */, D005F04A15950509007A8A1C /* EXTBlockMethod.h in Headers */, D005F04E15950509007A8A1C /* EXTBlockTarget.h in Headers */, D005F05215950509007A8A1C /* EXTConcreteProtocol.h in Headers */, @@ -684,7 +655,6 @@ buildActionMask = 2147483647; files = ( D005F04315950509007A8A1C /* EXTADT.h in Headers */, - D005F04515950509007A8A1C /* EXTAspect.h in Headers */, D005F04915950509007A8A1C /* EXTBlockMethod.h in Headers */, D005F04D15950509007A8A1C /* EXTBlockTarget.h in Headers */, D005F05115950509007A8A1C /* EXTConcreteProtocol.h in Headers */, @@ -730,7 +700,6 @@ buildRules = ( ); dependencies = ( - D06674E415990AB1001537C5 /* PBXTargetDependency */, ); name = "libextobjc (iOS)"; productName = "libextobjc (iOS)"; @@ -784,7 +753,6 @@ buildRules = ( ); dependencies = ( - D06674E615990AB4001537C5 /* PBXTargetDependency */, ); name = "libextobjc (OS X)"; productName = libextobjc; @@ -814,8 +782,8 @@ projectDirPath = ""; projectReferences = ( { - ProductGroup = D06674D815990AAB001537C5 /* Products */; - ProjectRef = D06674D715990AAB001537C5 /* libffi.xcodeproj */; + ProductGroup = 030C01A6181D153400C77CA9 /* Products */; + ProjectRef = 030C01A5181D153400C77CA9 /* libffi.xcodeproj */; }, ); projectRoot = ""; @@ -829,18 +797,18 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - D06674E015990AAB001537C5 /* libffi.a */ = { + 030C01AB181D153400C77CA9 /* libffi.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libffi.a; - remoteRef = D06674DF15990AAB001537C5 /* PBXContainerItemProxy */; + remoteRef = 030C01AA181D153400C77CA9 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - D06674E215990AAB001537C5 /* libffi.a */ = { + 030C01AD181D153400C77CA9 /* libffi.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; path = libffi.a; - remoteRef = D06674E115990AAB001537C5 /* PBXContainerItemProxy */; + remoteRef = 030C01AC181D153400C77CA9 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ @@ -867,27 +835,26 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D005F04815950509007A8A1C /* EXTAspect.m in Sources */, - D005F04C15950509007A8A1C /* EXTBlockMethod.m in Sources */, - D005F05015950509007A8A1C /* EXTBlockTarget.m in Sources */, - D005F05415950509007A8A1C /* EXTConcreteProtocol.m in Sources */, - D005F05A15950509007A8A1C /* EXTDispatchObject.m in Sources */, - D005F05E15950509007A8A1C /* EXTFinalMethod.m in Sources */, - D005F06415950509007A8A1C /* EXTMaybe.m in Sources */, - D005F06A15950509007A8A1C /* EXTMultiObject.m in Sources */, - D005F06E15950509007A8A1C /* EXTNil.m in Sources */, - D005F07615950509007A8A1C /* EXTPrivateMethod.m in Sources */, - D005F07A15950509007A8A1C /* EXTProtocolCategory.m in Sources */, - D005F07E15950509007A8A1C /* EXTRuntimeExtensions.m in Sources */, - D005F08215950509007A8A1C /* EXTSafeCategory.m in Sources */, - D005F08615950509007A8A1C /* EXTScope.m in Sources */, - D005F08E15950509007A8A1C /* EXTVarargs.m in Sources */, + 030C01FA181DADCF00C77CA9 /* EXTADT.m in Sources */, + 030C01FB181DADCF00C77CA9 /* EXTAnnotation.m in Sources */, + 030C01FD181DADCF00C77CA9 /* EXTBlockMethod.m in Sources */, + 030C01FE181DADCF00C77CA9 /* EXTBlockTarget.m in Sources */, + 030C01FF181DADCF00C77CA9 /* EXTConcreteProtocol.m in Sources */, + 030C0200181DADCF00C77CA9 /* EXTDispatchObject.m in Sources */, + 030C0201181DADCF00C77CA9 /* EXTFinalMethod.m in Sources */, + 030C0202181DADCF00C77CA9 /* EXTMaybe.m in Sources */, + 030C0203181DADCF00C77CA9 /* EXTMultimethod.m in Sources */, + 030C0204181DADCF00C77CA9 /* EXTMultiObject.m in Sources */, + 030C0205181DADCF00C77CA9 /* EXTNil.m in Sources */, + 030C0206181DADCF00C77CA9 /* EXTPrivateMethod.m in Sources */, + 030C0207181DADCF00C77CA9 /* EXTProtocolCategory.m in Sources */, + 030C0208181DADCF00C77CA9 /* EXTRuntimeExtensions.m in Sources */, + 030C0209181DADCF00C77CA9 /* EXTSafeCategory.m in Sources */, + 030C020A181DADCF00C77CA9 /* EXTScope.m in Sources */, + 030C020B181DADCF00C77CA9 /* EXTSelectorChecking.m in Sources */, + 030C020C181DADCF00C77CA9 /* EXTVarargs.m in Sources */, D005F09415950509007A8A1C /* NSInvocation+EXT.m in Sources */, D005F09815950509007A8A1C /* NSMethodSignature+EXT.m in Sources */, - D0FE94011596665D00F3AE1C /* EXTMultimethod.m in Sources */, - D0EF9C0015992F080066DFBC /* EXTADT.m in Sources */, - D09FB2FE159A459700A5F6A4 /* EXTSelectorChecking.m in Sources */, - D0E6A0F1159BB43B00FB92FC /* EXTAnnotation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -907,7 +874,6 @@ D002DAF813656CDF005348A5 /* EXTNilTest.m in Sources */, D0B9B0B513727EF800EC1224 /* EXTScopeTest.m in Sources */, D03EC9A3138A25F100559080 /* EXTCoroutineTest.m in Sources */, - D035A5BB148022B9006C1001 /* EXTAspectTest.m in Sources */, D0737D9414CB9438005BF183 /* EXTMaybeTest.m in Sources */, D0CD1BE7158F2A2A0039C845 /* EXTTupleTest.m in Sources */, D088C7BE159121A300C70CE2 /* EXTKeyPathCodingTest.m in Sources */, @@ -938,7 +904,6 @@ D002DAF913656CDF005348A5 /* EXTNilTest.m in Sources */, D0B9B0B613727EF800EC1224 /* EXTScopeTest.m in Sources */, D03EC9A4138A25F100559080 /* EXTCoroutineTest.m in Sources */, - D035A5BC148022B9006C1001 /* EXTAspectTest.m in Sources */, D0737D9514CB9438005BF183 /* EXTMaybeTest.m in Sources */, D0CD1BE8158F2A2A0039C845 /* EXTTupleTest.m in Sources */, D088C7BF159121A300C70CE2 /* EXTKeyPathCodingTest.m in Sources */, @@ -957,43 +922,32 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D005F04715950509007A8A1C /* EXTAspect.m in Sources */, - D005F04B15950509007A8A1C /* EXTBlockMethod.m in Sources */, - D005F04F15950509007A8A1C /* EXTBlockTarget.m in Sources */, - D005F05315950509007A8A1C /* EXTConcreteProtocol.m in Sources */, - D005F05915950509007A8A1C /* EXTDispatchObject.m in Sources */, - D005F05D15950509007A8A1C /* EXTFinalMethod.m in Sources */, - D005F06315950509007A8A1C /* EXTMaybe.m in Sources */, - D005F06915950509007A8A1C /* EXTMultiObject.m in Sources */, - D005F06D15950509007A8A1C /* EXTNil.m in Sources */, - D005F07515950509007A8A1C /* EXTPrivateMethod.m in Sources */, - D005F07915950509007A8A1C /* EXTProtocolCategory.m in Sources */, - D005F07D15950509007A8A1C /* EXTRuntimeExtensions.m in Sources */, - D005F08115950509007A8A1C /* EXTSafeCategory.m in Sources */, - D005F08515950509007A8A1C /* EXTScope.m in Sources */, - D005F08D15950509007A8A1C /* EXTVarargs.m in Sources */, + 030C01E7181DADBA00C77CA9 /* EXTADT.m in Sources */, + 030C01E8181DADBA00C77CA9 /* EXTAnnotation.m in Sources */, + 030C01EA181DADBA00C77CA9 /* EXTBlockMethod.m in Sources */, + 030C01EB181DADBA00C77CA9 /* EXTBlockTarget.m in Sources */, + 030C01EC181DADBA00C77CA9 /* EXTConcreteProtocol.m in Sources */, + 030C01ED181DADBA00C77CA9 /* EXTDispatchObject.m in Sources */, + 030C01EE181DADBA00C77CA9 /* EXTFinalMethod.m in Sources */, + 030C01EF181DADBA00C77CA9 /* EXTMaybe.m in Sources */, + 030C01F0181DADBA00C77CA9 /* EXTMultimethod.m in Sources */, + 030C01F1181DADBA00C77CA9 /* EXTMultiObject.m in Sources */, + 030C01F2181DADBA00C77CA9 /* EXTNil.m in Sources */, + 030C01F3181DADBA00C77CA9 /* EXTPrivateMethod.m in Sources */, + 030C01F4181DADBA00C77CA9 /* EXTProtocolCategory.m in Sources */, + 030C01F5181DADBA00C77CA9 /* EXTRuntimeExtensions.m in Sources */, + 030C01F6181DADBA00C77CA9 /* EXTSafeCategory.m in Sources */, + 030C01F7181DADBA00C77CA9 /* EXTScope.m in Sources */, + 030C01F8181DADBA00C77CA9 /* EXTSelectorChecking.m in Sources */, + 030C01F9181DADBA00C77CA9 /* EXTVarargs.m in Sources */, D005F09315950509007A8A1C /* NSInvocation+EXT.m in Sources */, D005F09715950509007A8A1C /* NSMethodSignature+EXT.m in Sources */, - D0FE94001596665D00F3AE1C /* EXTMultimethod.m in Sources */, - D0EF9BFF15992F080066DFBC /* EXTADT.m in Sources */, - D09FB2FD159A459700A5F6A4 /* EXTSelectorChecking.m in Sources */, - D0E6A0F0159BB43B00FB92FC /* EXTAnnotation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - D06674E415990AB1001537C5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libffi iOS"; - targetProxy = D06674E315990AB1001537C5 /* PBXContainerItemProxy */; - }; - D06674E615990AB4001537C5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "libffi OS X"; - targetProxy = D06674E515990AB4001537C5 /* PBXContainerItemProxy */; - }; D0CFB604128A8EB6006DC377 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = D2AAC07D0554694100DB518D /* libextobjc (OS X) */; @@ -1011,6 +965,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = D0919C5E146F99B900D680C9 /* Mac-StaticLibrary.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; GCC_PREFIX_HEADER = extobjc/extobjc_Prefix.pch; HEADER_SEARCH_PATHS = libffi/osx/include; INSTALL_PATH = /usr/local/lib; @@ -1023,6 +978,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = D0919C5E146F99B900D680C9 /* Mac-StaticLibrary.xcconfig */; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; GCC_PREFIX_HEADER = extobjc/extobjc_Prefix.pch; HEADER_SEARCH_PATHS = libffi/osx/include; INSTALL_PATH = /usr/local/lib; @@ -1074,6 +1030,7 @@ baseConfigurationReference = D0919C58146F99B900D680C9 /* iOS-StaticLibrary.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; GCC_PREFIX_HEADER = extobjc/extobjc_Prefix.pch; HEADER_SEARCH_PATHS = "libffi/ios/include/**"; PRODUCT_NAME = extobjc_iOS; @@ -1085,6 +1042,7 @@ baseConfigurationReference = D0919C58146F99B900D680C9 /* iOS-StaticLibrary.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; GCC_PREFIX_HEADER = extobjc/extobjc_Prefix.pch; HEADER_SEARCH_PATHS = "libffi/ios/include/**"; PRODUCT_NAME = extobjc_iOS; diff --git a/extobjc/EXTPassthrough.h b/extobjc/EXTPassthrough.h index ea65075a..f341e1d3 100644 --- a/extobjc/EXTPassthrough.h +++ b/extobjc/EXTPassthrough.h @@ -10,6 +10,7 @@ #import #import #import "metamacros.h" +#import "EXTRuntimeExtensions.h" /** * \@passthrough defines \a METHOD on \a CLASS to simply invoke a method on @@ -23,164 +24,261 @@ * the message to send. * * @code - -// -// OuterClass.h -// -@interface OuterClass : NSObject -@end - -@interface OuterClass (PassthroughMethods) -@property (nonatomic, getter = isEnabled) BOOL enabled; - -- (void)renamedMethod; -- (int)methodWithString:(NSString *)str; -@end - -// -// OuterClass.m -// -@interface InnerClass : NSObject -@property (nonatomic, getter = isEnabled) BOOL enabled; - -- (void)voidMethod; -- (int)methodWithString:(NSString *)str; -@end - -@interface OuterClass () -@property (nonatomic, strong) InnerClass *inner; -@end - -@implementation OuterClass -@passthrough(OuterClass, renamedMethod, self.inner, voidMethod); -@passthrough(OuterClass, methodWithString:, self.inner); -@passthrough(OuterClass, isEnabled, self.inner); -@passthrough(OuterClass, setEnabled:, self.inner); - -- (id)init { - self = [super init]; - if (!self) - return nil; - - self.inner = [InnerClass new]; - return self; -} - -@end - -@implementation InnerClass -... -@end - + + // + // OuterClass.h + // + @interface OuterClass : NSObject + @end + + @interface OuterClass (PassthroughMethods) + + - (void)renamedMethod; + - (int)methodWithString:(NSString *)str; + @end + + // + // OuterClass.m + // + @interface InnerClass : NSObject + + - (void)voidMethod; + - (int)methodWithString:(NSString *)str; + @end + + @interface OuterClass () + @property (nonatomic, strong) InnerClass *inner; + @end + + @implementation OuterClass + @passthrough(OuterClass, renamedMethod, self.inner, voidMethod); + @passthrough(OuterClass, methodWithString:, self.inner); + + - (id)init { + self = [super init]; + if (!self) + return nil; + + self.inner = [InnerClass new]; + return self; + } + + @end + + @implementation InnerClass + ... + @end + * @endcode * * @note \a METHOD must denote an instance method. * - * @note To avoid "incomplete implementation" warnings, passthrough methods and - * properties may be declared in a category on \a CLASS, as opposed to the main - * \@interface block. + * @note To avoid "incomplete implementation" warnings, passthrough methods may + * be declared in a category on \a CLASS, as opposed to the main \@interface + * block. + */ + +/* + * \@passthrough_property defines \a PROPERTY on \a CLASS to invoke the + * accessors for a property on another object and return the result. + * The macro finds the names of the setter and getter automatically. Like + * \@passthrough, the object to message should be the third argument to the + * macro. + * + * By default, the accessors on the messaged object are assumed to have the + * same names as the accessors on \a CLASS. \a PROPERTY may pass through to a + * a property of another name by passing a fourth argument to the macro, which + * should be the name of the property on the messaged class. + * + * @code + + // + // OuterClass.h + // + @interface OuterClass : NSObject + + @property (nonatomic, getter = hasFlakyCrust, setter = topWithFlakyCrust:) BOOL flakyCrust; + @property (strong, nonatomic) NSString * fruitType; + @property (nonatomic) BOOL aLaMode; + + @end + + @interface OuterClass (PassthroughMethods) + @property (nonatomic) NSTimeInterval bakingTime; + @end + + // + // InnerClass.m + // + @interface InnerClass : NSObject + + @property (nonatomic, getter = hasFlakyCrust, setter = topWithFlakyCrust:) BOOL flakyCrust; + @property (strong, nonatomic, setter = assignFilling:, getter = whatIsTheFilling) NSString * filling; + @property (nonatomic, getter = isALaMode) BOOL aLaMode; + @property (nonatomic) NSTimeInterval bakingTime; + + @end + + @implementation InnerClass + @end + + @interface OuterClass () + @property (nonatomic, strong) InnerClass *inner; + @end + + @implementation OuterClass + @passthrough_property(OuterClass, flakyCrust, self.inner); + @passthrough_property(OuterClass, fruitType, self.inner, filling); + @passthrough_property(OuterClass, aLaMode, self.inner, aLaMode); + + - (id)init { + self = [super init]; + if (!self) + return nil; + + self.inner = [InnerClass new]; + return self; + } + + @end + + @implementation OuterClass (PassthroughMethods) + @passthrough_property(OuterClass, bakingTime, self.inner); + @end + + * @endcode + * + * @note If the properties on the two classes have the same base names but + * different accessors, the property name must be re-specified as the fourth + * argument in order for the accessor name lookup to take place on the + * messaged class. (In the example code, this is the \c aLaMode case.) + * + * @note The property in the outer class uses a \@dynamic implementation + * directive to avoid auto-synthesis of accessors pre-empting the forwarding. + * This means that the \@property declaration and the \@passthrough_property + * must both be either in the same category or in the main \@interface and + * \@implementation blocks, as shown here. This means that passthrough methods + * and passthrough properties should not be declared in the same category; + * a "method definition not found" warning will be issued if the methods are + * declared but not defined, and if they are defined, no forwarding will take + * place. */ + +#define passthrough_property(CLASS, PROPERTY, ...) \ +dynamic PROPERTY; \ +passthrough_(__COUNTER__, CLASS, ext_getterNameForProperty(# CLASS, # PROPERTY), sel_getUid, \ +metamacro_if_eq(metamacro_argcount(__VA_ARGS__), 2) \ +(metamacro_head(__VA_ARGS__), passthrough_renamed_property_accessor(getter, __VA_ARGS__)) \ +(__VA_ARGS__)) \ +passthrough_(__COUNTER__, CLASS, ext_setterNameForProperty(# CLASS, # PROPERTY), sel_getUid, \ +metamacro_if_eq(metamacro_argcount(__VA_ARGS__), 2) \ +(metamacro_head(__VA_ARGS__), passthrough_renamed_property_accessor(setter, __VA_ARGS__)) \ +(__VA_ARGS__)) + #define passthrough(CLASS, METHOD, ...) \ - class CLASS; \ - \ - passthrough_(__COUNTER__, CLASS, METHOD, __VA_ARGS__) +class CLASS; \ +\ +passthrough_(__COUNTER__, CLASS, METHOD, @selector, __VA_ARGS__) /*** implementation details follow ***/ \ -#define passthrough_(ID, CLASS, METHOD, ...) \ - static id \ - (*metamacro_concat(ext_originalMethodSignatureForSelector_, ID)) \ - (id, SEL, SEL); \ - \ - static NSMethodSignature * \ - metamacro_concat(ext_methodSignatureForSelector_, ID) \ - (CLASS *self, SEL _cmd, SEL selector) { \ - if (selector != @selector(METHOD)) \ - return metamacro_concat(ext_originalMethodSignatureForSelector_, ID)(self, _cmd, selector); \ - \ - id inner = metamacro_head(__VA_ARGS__); \ - SEL innerSelector = passthrough_renamed_method(METHOD, __VA_ARGS__); \ - return [inner methodSignatureForSelector:innerSelector]; \ - } \ - \ - static BOOL \ - (*metamacro_concat(ext_originalRespondsToSelector_, ID)) \ - (id, SEL, SEL); \ - \ - static BOOL \ - metamacro_concat(ext_respondsToSelector_, ID) \ - (CLASS *self, SEL _cmd, SEL selector) { \ - if (selector != @selector(METHOD)) \ - return metamacro_concat(ext_originalRespondsToSelector_, ID)(self, _cmd, selector); \ - \ - id inner = metamacro_head(__VA_ARGS__); \ - SEL innerSelector = passthrough_renamed_method(METHOD, __VA_ARGS__); \ - return [inner respondsToSelector:innerSelector]; \ - } \ - \ - static void \ - (*metamacro_concat(ext_originalForwardInvocation_, ID)) \ - (id, SEL, id); \ - \ - static void \ - metamacro_concat(ext_forwardInvocation_, ID) \ - (CLASS *self, SEL _cmd, NSInvocation *invocation) { \ - if (invocation.selector != @selector(METHOD)) { \ - metamacro_concat(ext_originalForwardInvocation_, ID)(self, _cmd, invocation); \ - return; \ - } \ - \ - [invocation setTarget:metamacro_head(__VA_ARGS__)]; \ - [invocation setSelector:passthrough_renamed_method(METHOD, __VA_ARGS__)]; \ - [invocation invoke]; \ - } \ - \ - __attribute__((constructor)) \ - static void metamacro_concat(ext_passthrough_injection_, ID) (void) { \ - Class outerClass = objc_getClass(# CLASS); \ - \ - Method methodSignatureForSelector = class_getInstanceMethod(outerClass, @selector(methodSignatureForSelector:)); \ - Method respondsToSelector = class_getInstanceMethod(outerClass, @selector(respondsToSelector:)); \ - Method forwardInvocation = class_getInstanceMethod(outerClass, @selector(forwardInvocation:)); \ - \ - metamacro_concat(ext_originalMethodSignatureForSelector_, ID) = \ - (id (*)(id, SEL, SEL))method_getImplementation(methodSignatureForSelector); \ - \ - metamacro_concat(ext_originalRespondsToSelector_, ID) = \ - (BOOL (*)(id, SEL, SEL))method_getImplementation(respondsToSelector); \ - \ - metamacro_concat(ext_originalForwardInvocation_, ID) = \ - (void (*)(id, SEL, id))method_getImplementation(forwardInvocation); \ - \ - class_replaceMethod( \ - outerClass, \ - @selector(methodSignatureForSelector:), \ - (IMP)&metamacro_concat(ext_methodSignatureForSelector_, ID), \ - method_getTypeEncoding(methodSignatureForSelector) \ - ); \ - \ - class_replaceMethod( \ - outerClass, \ - @selector(respondsToSelector:), \ - (IMP)&metamacro_concat(ext_respondsToSelector_, ID), \ - method_getTypeEncoding(respondsToSelector) \ - ); \ - \ - class_replaceMethod( \ - outerClass, \ - @selector(forwardInvocation:), \ - (IMP)&metamacro_concat(ext_forwardInvocation_, ID), \ - method_getTypeEncoding(forwardInvocation) \ - ); \ - } +#define passthrough_(ID, CLASS, METHOD, SEL_GETTER, ...) \ +static id \ +(*metamacro_concat(ext_originalMethodSignatureForSelector_, ID)) \ +(id, SEL, SEL); \ +\ +static NSMethodSignature * \ +metamacro_concat(ext_methodSignatureForSelector_, ID) \ +(CLASS *self, SEL _cmd, SEL selector) { \ +if (selector != SEL_GETTER (METHOD)) \ +return metamacro_concat(ext_originalMethodSignatureForSelector_, ID)(self, _cmd, selector); \ +\ +id inner = metamacro_head(__VA_ARGS__); \ +SEL innerSelector = passthrough_renamed_method(METHOD, SEL_GETTER, __VA_ARGS__); \ +return [inner methodSignatureForSelector:innerSelector]; \ +} \ +\ +static BOOL \ +(*metamacro_concat(ext_originalRespondsToSelector_, ID)) \ +(id, SEL, SEL); \ +\ +static BOOL \ +metamacro_concat(ext_respondsToSelector_, ID) \ +(CLASS *self, SEL _cmd, SEL selector) { \ +if (selector != SEL_GETTER (METHOD)) \ +return metamacro_concat(ext_originalRespondsToSelector_, ID)(self, _cmd, selector); \ +\ +id inner = metamacro_head(__VA_ARGS__); \ +SEL innerSelector = passthrough_renamed_method(METHOD, SEL_GETTER, __VA_ARGS__); \ +return [inner respondsToSelector:innerSelector]; \ +} \ +\ +static void \ +(*metamacro_concat(ext_originalForwardInvocation_, ID)) \ +(id, SEL, id); \ +\ +static void \ +metamacro_concat(ext_forwardInvocation_, ID) \ +(CLASS *self, SEL _cmd, NSInvocation *invocation) { \ +if (invocation.selector != SEL_GETTER (METHOD)) { \ +metamacro_concat(ext_originalForwardInvocation_, ID)(self, _cmd, invocation); \ +return; \ +} \ +\ +[invocation setTarget:metamacro_head(__VA_ARGS__)]; \ +[invocation setSelector:passthrough_renamed_method(METHOD, SEL_GETTER, __VA_ARGS__)]; \ +[invocation invoke]; \ +} \ +\ +__attribute__((constructor)) \ +static void metamacro_concat(ext_passthrough_injection_, ID) (void) { \ +Class outerClass = objc_getClass(# CLASS); \ +\ +Method methodSignatureForSelector = class_getInstanceMethod(outerClass, @selector(methodSignatureForSelector:)); \ +Method respondsToSelector = class_getInstanceMethod(outerClass, @selector(respondsToSelector:)); \ +Method forwardInvocation = class_getInstanceMethod(outerClass, @selector(forwardInvocation:)); \ +\ +metamacro_concat(ext_originalMethodSignatureForSelector_, ID) = \ +(id (*)(id, SEL, SEL))method_getImplementation(methodSignatureForSelector); \ +\ +metamacro_concat(ext_originalRespondsToSelector_, ID) = \ +(BOOL (*)(id, SEL, SEL))method_getImplementation(respondsToSelector); \ +\ +metamacro_concat(ext_originalForwardInvocation_, ID) = \ +(void (*)(id, SEL, id))method_getImplementation(forwardInvocation); \ +\ +class_replaceMethod( \ +outerClass, \ +@selector(methodSignatureForSelector:), \ +(IMP)&metamacro_concat(ext_methodSignatureForSelector_, ID), \ +method_getTypeEncoding(methodSignatureForSelector) \ +); \ +\ +class_replaceMethod( \ +outerClass, \ +@selector(respondsToSelector:), \ +(IMP)&metamacro_concat(ext_respondsToSelector_, ID), \ +method_getTypeEncoding(respondsToSelector) \ +); \ +\ +class_replaceMethod( \ +outerClass, \ +@selector(forwardInvocation:), \ +(IMP)&metamacro_concat(ext_forwardInvocation_, ID), \ +method_getTypeEncoding(forwardInvocation) \ +); \ +} + +#define passthrough_renamed_method(METHOD, SEL_GETTER, ...) \ +metamacro_if_eq(metamacro_argcount(__VA_ARGS__), 2) \ +( \ +/* the renamed method follows the passthrough target */ \ +SEL_GETTER (metamacro_at(1, __VA_ARGS__)) \ +) \ +( \ +/* no renaming */ \ +SEL_GETTER (METHOD) \ +) -#define passthrough_renamed_method(METHOD, ...) \ - @selector(metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__)) \ - ( \ - /* no renaming */ \ - METHOD \ - ) \ - ( \ - /* the renamed method follows the passthrough target */ \ - metamacro_at(1, __VA_ARGS__) \ - ) \ - ) +#define passthrough_renamed_property_accessor(G_OR_S, ...) \ +metamacro_concat(ext_, metamacro_concat(G_OR_S, NameForProperty)) \ +(object_getClassName(metamacro_head(__VA_ARGS__)), metamacro_stringify(metamacro_at(1, __VA_ARGS__))) diff --git a/extobjc/EXTRuntimeExtensions.h b/extobjc/EXTRuntimeExtensions.h index ca058267..29295388 100644 --- a/extobjc/EXTRuntimeExtensions.h +++ b/extobjc/EXTRuntimeExtensions.h @@ -276,6 +276,26 @@ Method ext_getImmediateInstanceMethod (Class aClass, SEL aSelector); */ BOOL ext_getPropertyAccessorsForClass (objc_property_t property, Class aClass, Method *getter, Method *setter); +/** + * Returns the name of the setter for \a property on the given class, whether + * the name was specified as part of the property's declaration or + * automatically generated. + * + * @note An autorelease pool must in place when this function is called, and + * the returned string will be invalid when that pool is drained. + */ +const char *ext_setterNameForProperty (const char *class_name, const char *prop_name); + +/** + * Returns the name of the getter for \a property on the given class, whether + * the name was specified as part of the property's declaration or + * automatically generated. + * + * @note An autorelease pool must in place when this function is called, and + * the returned string will be invalid when that pool is drained. + */ +const char *ext_getterNameForProperty (const char *class_name, const char *prop_name); + /** * For all classes registered with the runtime, invokes \c * methodSignatureForSelector: and \c instanceMethodSignatureForSelector: to diff --git a/extobjc/EXTRuntimeExtensions.m b/extobjc/EXTRuntimeExtensions.m index 7340b613..ea677562 100644 --- a/extobjc/EXTRuntimeExtensions.m +++ b/extobjc/EXTRuntimeExtensions.m @@ -701,7 +701,7 @@ BOOL ext_getPropertyAccessorsForClass (objc_property_t property, Class aClass, M SEL setterName = attributes->setter; free(attributes); - attributes = NO; + attributes = NULL; /* * set up an autorelease pool in case this sends aClass its first message @@ -725,6 +725,39 @@ BOOL ext_getPropertyAccessorsForClass (objc_property_t property, Class aClass, M return YES; } +/** + * Wraps the bytes in \a buf of \a length with an autoreleased NSData instance. + */ +static NSData * putBufferIntoAutoreleasePool (void *buf, size_t length) { + return [NSData dataWithBytesNoCopy:buf length:length freeWhenDone:YES]; +} + +const char *ext_setterNameForProperty (const char *class_name, const char *prop_name) { + objc_property_t prop = class_getProperty(objc_getClass(class_name), prop_name); + + char *setter_name = property_copyAttributeValue(prop, "S"); + + // Construct the standard setter name + if (!setter_name) { + setter_name = calloc(256, sizeof(char)); + snprintf(setter_name, 256, "set%c%s:", toupper(prop_name[0]), prop_name+1); + } + + putBufferIntoAutoreleasePool(setter_name, 256); + + return setter_name; +} + +const char *ext_getterNameForProperty (const char *class_name, const char *prop_name) { + objc_property_t prop = class_getProperty(objc_getClass(class_name), prop_name); + + char *getter_name = property_copyAttributeValue(prop, "G");] + + putBufferIntoAutoreleasePool(getter_name, 256); + + return getter_name ?: prop_name; +} + NSMethodSignature *ext_globalMethodSignatureForSelector (SEL aSelector) { // set up a simplistic cache to avoid repeatedly scouring every class in the // runtime