From 1ac2aa943df2874a832795de54c6b4d1186fb643 Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Thu, 19 May 2016 22:12:08 -0700 Subject: [PATCH 1/4] Add ability to disable automatic exception catching in BFTask. --- Bolts.xcodeproj/project.pbxproj | 32 ++++++++++++++++++++++++++++++++ Bolts/Common/BFTask+Exceptions.h | 32 ++++++++++++++++++++++++++++++++ Bolts/Common/BFTask+Exceptions.m | 24 ++++++++++++++++++++++++ Bolts/Common/BFTask.m | 13 +++++++++---- Bolts/Common/Bolts.h | 1 + 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 Bolts/Common/BFTask+Exceptions.h create mode 100644 Bolts/Common/BFTask+Exceptions.m diff --git a/Bolts.xcodeproj/project.pbxproj b/Bolts.xcodeproj/project.pbxproj index 589b974f9..69349a518 100644 --- a/Bolts.xcodeproj/project.pbxproj +++ b/Bolts.xcodeproj/project.pbxproj @@ -96,6 +96,20 @@ 819573EA1C2B8ECB00BFCA39 /* BFTaskCompletionSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 8103FA5219900A84000BAE3F /* BFTaskCompletionSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; 819573EC1C2B8ECB00BFCA39 /* Bolts.h in Headers */ = {isa = PBXBuildFile; fileRef = 8103FA5419900A84000BAE3F /* Bolts.h */; settings = {ATTRIBUTES = (Public, ); }; }; 819573ED1C2B8ECB00BFCA39 /* BFCancellationToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C60AEBD1ACF08F300747DD7 /* BFCancellationToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062A1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062B1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062C1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062D1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062E1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD062F1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD06301CEED28A00497F47 /* BFTask+Exceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81CD06331CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06341CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06351CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06361CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06371CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06381CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; + 81CD06391CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */; }; 81D0EE7D19AFA8260000AE75 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 81D0EE7C19AFA8260000AE75 /* UIKit.framework */; }; 81D0EE8319AFAA0E0000AE75 /* Bolts.h in Headers */ = {isa = PBXBuildFile; fileRef = 8103FA5419900A84000BAE3F /* Bolts.h */; settings = {ATTRIBUTES = (Public, ); }; }; 81D0EE8519AFAA190000AE75 /* BFTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 8103FA5019900A84000BAE3F /* BFTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -274,6 +288,8 @@ 8178F99E1BB0F8A600AD289D /* watchOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "watchOS-Info.plist"; path = "Resources/watchOS-Info.plist"; sourceTree = ""; }; 819573F11C2B8ECB00BFCA39 /* Bolts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bolts.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 819573F31C2B8EF400BFCA39 /* Bolts-watchOS-Dynamic.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Bolts-watchOS-Dynamic.xcconfig"; sourceTree = ""; }; + 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BFTask+Exceptions.h"; sourceTree = ""; }; + 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BFTask+Exceptions.m"; sourceTree = ""; }; 81D0EE7C19AFA8260000AE75 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; 81DC1A611B7A7F4000F491DC /* ExecutorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExecutorTests.m; sourceTree = ""; }; 81E94D6A1C2B8BF200A6291E /* Bolts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bolts.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -428,6 +444,8 @@ 8103FA5519900A84000BAE3F /* Bolts.m */, 8103FA5019900A84000BAE3F /* BFTask.h */, 8103FA5119900A84000BAE3F /* BFTask.m */, + 81CD06291CEED28A00497F47 /* BFTask+Exceptions.h */, + 81CD06321CEED2BC00497F47 /* BFTask+Exceptions.m */, 8103FA5219900A84000BAE3F /* BFTaskCompletionSource.h */, 8103FA5319900A84000BAE3F /* BFTaskCompletionSource.m */, 8103FA4E19900A84000BAE3F /* BFExecutor.h */, @@ -628,6 +646,7 @@ buildActionMask = 2147483647; files = ( 1D5D7DBA1BE3CE8200FD67C7 /* BFWebViewAppLinkResolver.h in Headers */, + 81CD062B1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 1D5D7DBB1BE3CE8200FD67C7 /* BFCancellationTokenRegistration.h in Headers */, 1D5D7DBC1BE3CE8200FD67C7 /* BFTask.h in Headers */, 1D5D7DBD1BE3CE8200FD67C7 /* BFAppLinkNavigation.h in Headers */, @@ -655,6 +674,7 @@ buildActionMask = 2147483647; files = ( 8178F9901BB0F87700AD289D /* BFCancellationTokenRegistration.h in Headers */, + 81CD062F1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 8178F9911BB0F87700AD289D /* BFTask.h in Headers */, 8178F9921BB0F87700AD289D /* BFCancellationTokenSource.h in Headers */, 8178F9931BB0F87700AD289D /* BFExecutor.h in Headers */, @@ -669,6 +689,7 @@ buildActionMask = 2147483647; files = ( 819573E51C2B8ECB00BFCA39 /* BFCancellationTokenRegistration.h in Headers */, + 81CD06301CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 819573E61C2B8ECB00BFCA39 /* BFTask.h in Headers */, 819573E71C2B8ECB00BFCA39 /* BFCancellationTokenSource.h in Headers */, 819573E81C2B8ECB00BFCA39 /* BFExecutor.h in Headers */, @@ -683,6 +704,7 @@ buildActionMask = 2147483647; files = ( 7CA39C931ADE715400DD78CC /* BFCancellationTokenRegistration.h in Headers */, + 81CD062C1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 81D0EE8519AFAA190000AE75 /* BFTask.h in Headers */, 7C60AECA1ACF1A0B00747DD7 /* BFCancellationTokenSource.h in Headers */, 81D0EE8819AFAA240000AE75 /* BFExecutor.h in Headers */, @@ -697,6 +719,7 @@ buildActionMask = 2147483647; files = ( 81E94D5E1C2B8BF200A6291E /* BFCancellationTokenRegistration.h in Headers */, + 81CD062E1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 81E94D5F1C2B8BF200A6291E /* BFTask.h in Headers */, 81E94D601C2B8BF200A6291E /* BFCancellationTokenSource.h in Headers */, 81E94D611C2B8BF200A6291E /* BFExecutor.h in Headers */, @@ -711,6 +734,7 @@ buildActionMask = 2147483647; files = ( 81ED94311BE1481900795F05 /* BFWebViewAppLinkResolver.h in Headers */, + 81CD062A1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, 81ED941D1BE147CF00795F05 /* BFCancellationTokenRegistration.h in Headers */, 81ED941E1BE147CF00795F05 /* BFTask.h in Headers */, 81ED942E1BE1481900795F05 /* BFAppLinkNavigation.h in Headers */, @@ -738,6 +762,7 @@ buildActionMask = 2147483647; files = ( F5AFC9F61BA752750076E927 /* BFCancellationTokenRegistration.h in Headers */, + 81CD062D1CEED28A00497F47 /* BFTask+Exceptions.h in Headers */, F5AFC9F71BA752750076E927 /* BFTask.h in Headers */, F5AFC9F81BA752750076E927 /* BFCancellationTokenSource.h in Headers */, F5AFC9F91BA752750076E927 /* BFExecutor.h in Headers */, @@ -1027,6 +1052,7 @@ 1D5D7DAB1BE3CE8200FD67C7 /* BFAppLinkReturnToRefererView.m in Sources */, 1D5D7DAC1BE3CE8200FD67C7 /* BFTask.m in Sources */, 1D5D7DAD1BE3CE8200FD67C7 /* Bolts.m in Sources */, + 81CD06341CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 1D5D7DAE1BE3CE8200FD67C7 /* BFCancellationTokenRegistration.m in Sources */, 1D5D7DAF1BE3CE8200FD67C7 /* BFCancellationTokenSource.m in Sources */, 1D5D7DB01BE3CE8200FD67C7 /* BFMeasurementEvent.m in Sources */, @@ -1058,6 +1084,7 @@ 8178F9891BB0F87700AD289D /* BFCancellationTokenRegistration.m in Sources */, 8178F98A1BB0F87700AD289D /* BFCancellationTokenSource.m in Sources */, 8178F98B1BB0F87700AD289D /* BFExecutor.m in Sources */, + 81CD06381CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 8178F98C1BB0F87700AD289D /* BFCancellationToken.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1072,6 +1099,7 @@ 819573DE1C2B8ECB00BFCA39 /* BFCancellationTokenRegistration.m in Sources */, 819573DF1C2B8ECB00BFCA39 /* BFCancellationTokenSource.m in Sources */, 819573E01C2B8ECB00BFCA39 /* BFExecutor.m in Sources */, + 81CD06391CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 819573E11C2B8ECB00BFCA39 /* BFCancellationToken.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1086,6 +1114,7 @@ 81E94D571C2B8BF200A6291E /* BFCancellationTokenRegistration.m in Sources */, 81E94D581C2B8BF200A6291E /* BFCancellationTokenSource.m in Sources */, 81E94D591C2B8BF200A6291E /* BFExecutor.m in Sources */, + 81CD06371CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 81E94D5A1C2B8BF200A6291E /* BFCancellationToken.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1100,6 +1129,7 @@ 81ED94361BE1481900795F05 /* BFAppLinkReturnToRefererView.m in Sources */, 81ED94141BE147CF00795F05 /* BFTask.m in Sources */, 81ED94151BE147CF00795F05 /* Bolts.m in Sources */, + 81CD06331CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 81ED94161BE147CF00795F05 /* BFCancellationTokenRegistration.m in Sources */, 81ED94171BE147CF00795F05 /* BFCancellationTokenSource.m in Sources */, 81ED943C1BE1481900795F05 /* BFMeasurementEvent.m in Sources */, @@ -1144,6 +1174,7 @@ 7CA39C951ADE715400DD78CC /* BFCancellationTokenRegistration.m in Sources */, 7C60AECB1ACF1A0D00747DD7 /* BFCancellationTokenSource.m in Sources */, 8103FA6919900A84000BAE3F /* BFExecutor.m in Sources */, + 81CD06351CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, 7C60AEC91ACF1A0900747DD7 /* BFCancellationToken.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1158,6 +1189,7 @@ F5AFC9EF1BA752750076E927 /* BFCancellationTokenRegistration.m in Sources */, F5AFC9F01BA752750076E927 /* BFCancellationTokenSource.m in Sources */, F5AFC9F11BA752750076E927 /* BFExecutor.m in Sources */, + 81CD06361CEED2BC00497F47 /* BFTask+Exceptions.m in Sources */, F5AFC9F21BA752750076E927 /* BFCancellationToken.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Bolts/Common/BFTask+Exceptions.h b/Bolts/Common/BFTask+Exceptions.h new file mode 100644 index 000000000..41b633c65 --- /dev/null +++ b/Bolts/Common/BFTask+Exceptions.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#pragma once + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Returns whether all instances of `BFTask` should automatically @try/@catch exceptions in continuation blocks. Default: `YES`. + + @return Boolean value indicating whether exceptions are being caught. + */ +extern BOOL BFTaskCatchesExceptions(void) +__attribute__((deprecated("This is temporary API and will be removed in a future release."))); + +/** + Set whether all instances of `BFTask` should automatically @try/@catch exceptions in continuation blocks. Default: `YES`. + + @param catchExceptions Boolean value indicating whether exceptions shoudl be caught. + */ +extern void BFTaskSetCatchesExceptions(BOOL catchExceptions) +__attribute__((deprecated("This is a temporary API and will be removed in a future release."))); + +NS_ASSUME_NONNULL_END diff --git a/Bolts/Common/BFTask+Exceptions.m b/Bolts/Common/BFTask+Exceptions.m new file mode 100644 index 000000000..928197e5e --- /dev/null +++ b/Bolts/Common/BFTask+Exceptions.m @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "BFTask+Exceptions.h" + +NS_ASSUME_NONNULL_BEGIN + +static BOOL taskCatchExceptions = YES; + +BOOL BFTaskCatchesExceptions(void) { + return taskCatchExceptions; +} + +void BFTaskSetCatchesExceptions(BOOL catchExceptions) { + taskCatchExceptions = catchExceptions; +} + +NS_ASSUME_NONNULL_END diff --git a/Bolts/Common/BFTask.m b/Bolts/Common/BFTask.m index 68436ec60..e83eda98d 100644 --- a/Bolts/Common/BFTask.m +++ b/Bolts/Common/BFTask.m @@ -13,6 +13,7 @@ #import #import "Bolts.h" +#import "BFTask+Exceptions.h" NS_ASSUME_NONNULL_BEGIN @@ -394,11 +395,15 @@ - (BFTask *)continueWithExecutor:(BFExecutor *)executor } id result = nil; - @try { + if (BFTaskCatchesExceptions()) { + @try { + result = block(self); + } @catch (NSException *exception) { + tcs.exception = exception; + return; + } + } else { result = block(self); - } @catch (NSException *exception) { - tcs.exception = exception; - return; } if ([result isKindOfClass:[BFTask class]]) { diff --git a/Bolts/Common/Bolts.h b/Bolts/Common/Bolts.h index 033124a15..907e4a2b6 100644 --- a/Bolts/Common/Bolts.h +++ b/Bolts/Common/Bolts.h @@ -13,6 +13,7 @@ #import #import #import +#import #import #if __has_include() && TARGET_OS_IPHONE && !TARGET_OS_WATCH && !TARGET_OS_TV From f60c65fac1d449e95b85b380509dfe41c876c24c Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Fri, 20 May 2016 13:55:36 -0700 Subject: [PATCH 2/4] Deprecate BFTask exception catching. --- Bolts/Common/BFTask.h | 20 ++++++++++++--- Bolts/Common/BFTask.m | 35 +++++++++++++++++++++------ Bolts/Common/BFTaskCompletionSource.h | 10 ++++++-- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/Bolts/Common/BFTask.h b/Bolts/Common/BFTask.h index 3cd040555..ccf577876 100644 --- a/Bolts/Common/BFTask.h +++ b/Bolts/Common/BFTask.h @@ -26,8 +26,11 @@ extern NSInteger const kBFMultipleErrorsError; /*! An exception that is thrown if there was multiple exceptions on . + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -extern NSString *const BFTaskMultipleExceptionsException; +extern NSString *const BFTaskMultipleExceptionsException +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); /*! An error userInfo key used if there were multiple errors on . @@ -38,8 +41,11 @@ extern NSString *const BFTaskMultipleErrorsUserInfoKey; /*! An error userInfo key used if there were multiple exceptions on . Value type is `NSArray *`. + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -extern NSString *const BFTaskMultipleExceptionsUserInfoKey; +extern NSString *const BFTaskMultipleExceptionsUserInfoKey +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); @class BFExecutor; @class BFTask; @@ -71,8 +77,11 @@ typedef __nullable id(^BFContinuationBlock)(BFTask *task); /*! Creates a task that is already completed with the given exception. @param exception The exception for the task. + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -+ (instancetype)taskWithException:(NSException *)exception; ++ (instancetype)taskWithException:(NSException *)exception +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); /*! Creates a task that is already cancelled. @@ -143,8 +152,11 @@ typedef __nullable id(^BFContinuationBlock)(BFTask *task); /*! The exception of a failed task. + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -@property (nullable, nonatomic, strong, readonly) NSException *exception; +@property (nullable, nonatomic, strong, readonly) NSException *exception +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); /*! Whether this task has been cancelled. diff --git a/Bolts/Common/BFTask.m b/Bolts/Common/BFTask.m index e83eda98d..894583456 100644 --- a/Bolts/Common/BFTask.m +++ b/Bolts/Common/BFTask.m @@ -128,9 +128,12 @@ + (instancetype)taskForCompletionOfAllTasks:(nullable NSArray *)tasks BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource]; for (BFTask *task in tasks) { [task continueWithBlock:^id(BFTask *task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (task.exception) { @synchronized (lock) { [exceptions addObject:task.exception]; +#pragma clang diagnostic pop } } else if (task.error) { @synchronized (lock) { @@ -142,15 +145,17 @@ + (instancetype)taskForCompletionOfAllTasks:(nullable NSArray *)tasks if (OSAtomicDecrement32Barrier(&total) == 0) { if (exceptions.count > 0) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (exceptions.count == 1) { tcs.exception = [exceptions firstObject]; } else { - NSException *exception = - [NSException exceptionWithName:BFTaskMultipleExceptionsException - reason:@"There were multiple exceptions." - userInfo:@{ BFTaskMultipleExceptionsUserInfoKey: exceptions }]; + NSException *exception = [NSException exceptionWithName:BFTaskMultipleExceptionsException + reason:@"There were multiple exceptions." + userInfo:@{ BFTaskMultipleExceptionsUserInfoKey: exceptions }]; tcs.exception = exception; } +#pragma clang diagnostic pop } else if (errors.count > 0) { if (errors.count == 1) { tcs.error = [errors firstObject]; @@ -195,9 +200,12 @@ + (instancetype)taskForCompletionOfAnyTask:(nullable NSArray *)tasks BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource]; for (BFTask *task in tasks) { [task continueWithBlock:^id(BFTask *task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (task.exception != nil) { @synchronized(lock) { [exceptions addObject:task.exception]; +#pragma clang diagnostic pop } } else if (task.error != nil) { @synchronized(lock) { @@ -216,14 +224,16 @@ + (instancetype)taskForCompletionOfAnyTask:(nullable NSArray *)tasks if (cancelled > 0) { [source cancel]; } else if (exceptions.count > 0) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (exceptions.count == 1) { source.exception = exceptions.firstObject; } else { - NSException *exception = - [NSException exceptionWithName:BFTaskMultipleExceptionsException - reason:@"There were multiple exceptions." - userInfo:@{ @"exceptions": exceptions }]; + NSException *exception = [NSException exceptionWithName:BFTaskMultipleExceptionsException + reason:@"There were multiple exceptions." + userInfo:@{ BFTaskMultipleExceptionsUserInfoKey: exceptions }]; source.exception = exception; +#pragma clang diagnostic pop } } else if (errors.count > 0) { if (errors.count == 1) { @@ -395,24 +405,33 @@ - (BFTask *)continueWithExecutor:(BFExecutor *)executor } id result = nil; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (BFTaskCatchesExceptions()) { @try { result = block(self); } @catch (NSException *exception) { + NSLog(@"[Bolts] Warning: `BFTask` caught an exception in the continuation block." + @" This behavior is discouraged and will be removed in a future release." + @" Caught Exception: %@", exception); tcs.exception = exception; return; } } else { result = block(self); } +#pragma clang diagnostic pop if ([result isKindOfClass:[BFTask class]]) { id (^setupWithTask) (BFTask *) = ^id(BFTask *task) { if (cancellationToken.cancellationRequested || task.cancelled) { [tcs cancel]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" } else if (task.exception) { tcs.exception = task.exception; +#pragma clang diagnostic pop } else if (task.error) { tcs.error = task.error; } else { diff --git a/Bolts/Common/BFTaskCompletionSource.h b/Bolts/Common/BFTaskCompletionSource.h index a403553fb..18810bc83 100644 --- a/Bolts/Common/BFTaskCompletionSource.h +++ b/Bolts/Common/BFTaskCompletionSource.h @@ -49,8 +49,11 @@ NS_ASSUME_NONNULL_BEGIN Completes the task by setting an exception. Attempting to set this for a completed task will raise an exception. @param exception The exception for the task. + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -- (void)setException:(NSException *)exception; +- (void)setException:(NSException *)exception +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); /*! Completes the task by marking it as cancelled. @@ -75,8 +78,11 @@ NS_ASSUME_NONNULL_BEGIN Sets the exception of the task if it wasn't already completed. @param exception The exception for the task. @returns whether the new value was set. + + @deprecated `BFTask` exception handling is deprecated and will be removed in a future release. */ -- (BOOL)trySetException:(NSException *)exception; +- (BOOL)trySetException:(NSException *)exception +__attribute__((deprecated("`BFTask` exception handling is deprecated and will be removed in a future release."))); /*! Sets the cancellation state of the task if it wasn't already completed. From f3e4f506d4b86dc41ee7056ad71ae73fd0a45059 Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Fri, 20 May 2016 13:55:57 -0700 Subject: [PATCH 3/4] Add deprecation ignore for warnings in tests. --- BoltsTests/ExecutorTests.m | 3 +++ BoltsTests/TaskTests.m | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/BoltsTests/ExecutorTests.m b/BoltsTests/ExecutorTests.m index 8474bcdf5..53c750bab 100644 --- a/BoltsTests/ExecutorTests.m +++ b/BoltsTests/ExecutorTests.m @@ -38,7 +38,10 @@ - (void)testExecuteOnDispatchQueue { BFTask *task = [BFTask taskWithResult:nil]; task = [task continueWithExecutor:queueExecutor withBlock:^id(BFTask *task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertEqual(queue, dispatch_get_current_queue()); +#pragma clang diagnostic pop return nil; }]; [task waitUntilFinished]; diff --git a/BoltsTests/TaskTests.m b/BoltsTests/TaskTests.m index 8c9d83cb8..ae0e897a3 100644 --- a/BoltsTests/TaskTests.m +++ b/BoltsTests/TaskTests.m @@ -102,8 +102,11 @@ - (void)testBasicContinueWithException { [NSException raise:NSInternalInconsistencyException format:message]; return nil; }] continueWithBlock:^id(BFTask *task) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertNotNil(task.exception, @"Task should have failed."); XCTAssertEqualObjects(message, task.exception.description); +#pragma clang diagnostic pop return nil; }] waitUntilFinished]; } @@ -171,6 +174,8 @@ - (void)testFinishLaterWithError { - (void)testFinishLaterWithException { NSString *message = @"This is expected."; BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" BFTask *task = [tcs.task continueWithBlock:^id(BFTask *task) { XCTAssertNotNil(task.exception, @"Task should have failed."); XCTAssertEqualObjects(message, task.exception.description); @@ -179,6 +184,7 @@ - (void)testFinishLaterWithException { [tcs setException:[NSException exceptionWithName:NSInternalInconsistencyException reason:message userInfo:nil]]; +#pragma clang diagnostic pop [task waitUntilFinished]; } @@ -336,7 +342,10 @@ - (void)testTaskForCompletionOfAllTasksSuccess { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNil(task.error); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertNil(task.exception); +#pragma clang diagnostic pop XCTAssertFalse(task.isCancelled); for (int i = 0; i < kTaskCount; ++i) { @@ -362,6 +371,8 @@ - (void)testTaskForCompletionOfAllTasksOneException { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNil(task.error); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertNotNil(task.exception); XCTAssertFalse(task.isCancelled); @@ -374,6 +385,7 @@ - (void)testTaskForCompletionOfAllTasksOneException { XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]); } } +#pragma clang diagnostic pop return nil; }] waitUntilFinished]; } @@ -394,6 +406,8 @@ - (void)testTaskForCompletionOfAllTasksTwoExceptions { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNil(task.error); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertNotNil(task.exception); XCTAssertFalse(task.isCancelled); @@ -411,6 +425,7 @@ - (void)testTaskForCompletionOfAllTasksTwoExceptions { XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]); } } +#pragma clang diagnostic pop return nil; }] waitUntilFinished]; } @@ -433,7 +448,6 @@ - (void)testTaskForCompletionOfAllTasksOneError { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNotNil(task.error); - XCTAssertNil(task.exception); XCTAssertFalse(task.isCancelled); XCTAssertEqualObjects(@"BoltsTests", task.error.domain); @@ -468,7 +482,6 @@ - (void)testTaskForCompletionOfAllTasksTwoErrors { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNotNil(task.error); - XCTAssertNil(task.exception); XCTAssertFalse(task.isCancelled); XCTAssertEqualObjects(@"bolts", task.error.domain); @@ -507,7 +520,6 @@ - (void)testTaskForCompletionOfAllTasksCancelled { [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) { XCTAssertNil(task.error); - XCTAssertNil(task.exception); XCTAssertTrue(task.isCancelled); for (int i = 0; i < kTaskCount; ++i) { @@ -566,6 +578,8 @@ - (void)testTaskForCompletionOfAllTasksErrorCancelledSuccess { } - (void)testTaskForCompletionOfAllTasksExceptionCancelledSuccess { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" NSException *exception = [NSException exceptionWithName:@"" reason:@"" userInfo:nil]; BFTask *exceptionTask = [BFTask taskWithException:exception]; BFTask *cancelledTask = [BFTask cancelledTask]; @@ -576,9 +590,12 @@ - (void)testTaskForCompletionOfAllTasksExceptionCancelledSuccess { XCTAssertTrue(allTasks.faulted, @"Task should be faulted"); XCTAssertNil(allTasks.error, @"Task shoud not have error"); XCTAssertNotNil(allTasks.exception, @"Task should have exception"); +#pragma clang diagnostic pop } - (void)testTaskForCompletionOfAllTasksExceptionErrorCancelledSuccess { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" BFTask *errorTask = [BFTask taskWithError:[NSError new]]; BFTask *exceptionTask = [BFTask taskWithException:[NSException new]]; BFTask *cancelledTask = [BFTask cancelledTask]; @@ -589,6 +606,7 @@ - (void)testTaskForCompletionOfAllTasksExceptionErrorCancelledSuccess { XCTAssertTrue(allTasks.faulted, @"Task should be faulted"); XCTAssertNotNil(allTasks.error, @"Task should have error"); XCTAssertNil(allTasks.exception, @"Task should not have exception"); +#pragma clang diagnostic pop } - (void)testTaskForCompletionOfAllTasksErrorCancelled { @@ -682,13 +700,11 @@ - (void)testTasksForTaskForCompletionOfAnyTasksWithError { } - (void)testTasksForTaskForCompletionOfAnyTasksWithNilArray { - BFTask *task = [BFTask taskForCompletionOfAnyTask:nil]; [task waitUntilFinished]; XCTAssertNil(task.result); XCTAssertNil(task.error); - XCTAssertNil(task.exception); } - (void)testTasksForTaskForCompletionOfAnyTasksAllErrors { @@ -742,7 +758,10 @@ - (void)testTaskFromExecutor { BFExecutor *queueExecutor = [BFExecutor executorWithDispatchQueue:queue]; BFTask *task = [BFTask taskFromExecutor:queueExecutor withBlock:^id() { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertEqual(queue, dispatch_get_current_queue()); +#pragma clang diagnostic pop return @"foo"; }]; [task waitUntilFinished]; @@ -817,6 +836,8 @@ - (void)testTrySetError { - (void)testSetException { BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:@"test" userInfo:nil]; taskCompletionSource.exception = exception; XCTAssertThrowsSpecificNamed([taskCompletionSource setException:exception], NSException, NSInternalInconsistencyException); @@ -824,11 +845,14 @@ - (void)testSetException { XCTAssertTrue(taskCompletionSource.task.completed); XCTAssertTrue(taskCompletionSource.task.faulted); XCTAssertEqualObjects(taskCompletionSource.task.exception, exception); +#pragma clang diagnostic pop } - (void)testTrySetException { BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:@"test" userInfo:nil]; [taskCompletionSource trySetException:exception]; [taskCompletionSource trySetException:exception]; @@ -836,6 +860,7 @@ - (void)testTrySetException { XCTAssertTrue(taskCompletionSource.task.completed); XCTAssertTrue(taskCompletionSource.task.faulted); XCTAssertEqualObjects(taskCompletionSource.task.exception, exception); +#pragma clang diagnostic pop } - (void)testSetCancelled { From f6ef4fa38ba0f2a674b91272611589a97e023b47 Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Fri, 20 May 2016 17:36:37 -0700 Subject: [PATCH 4/4] Lint podspec with libraries first to avoid framework collision. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8a1012ea4..bec19eaa9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,8 +37,8 @@ script: set -o pipefail xcodebuild test -project Bolts.xcodeproj -sdk appletvsimulator -scheme Bolts-tvOS -destination "platform=tvOS Simulator,name=Apple TV 1080p" -configuration Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c elif [ "$TEST_TYPE" = CocoaPods ]; then - pod lib lint Bolts.podspec pod lib lint --use-libraries Bolts.podspec + pod lib lint Bolts.podspec elif [ "$TEST_TYPE" = Carthage ]; then carthage build --no-skip-current fi