Merge pull request #2243 from ahankinson/new-CFError-CPError

New: CFError and Updated CPError
This commit is contained in:
Antoine Mercadal committed 2015-01-08 17:33:31 -08:00
commit d3490f6a2e
9 files changed
+432 -27

No files matched your search

+1 -1
View File
@@ -53,7 +53,7 @@
@param aType the structure or object type
@param anObject the object to be encoded
*/
- (void)encodeValueOfObjCType:(CPString)aType at:(id)anObject
- (void)encodeValueOfObjJType:(CPString)aType at:(id)anObject
{
_CPRaiseInvalidAbstractInvocation(self, _cmd);
}
+97 -26
View File
@@ -24,31 +24,52 @@
@import "CPObject.j"
@import "CPString.j"
CPCappuccinoErrorDomain = CPCocoaErrorDomain = @"CPCappuccinoErrorDomain";
// CPPOSIXErrorDomain = @"CPPOSIXErrorDomain";
// CPOSStatusErrorDomain = @"CPOSStatusErrorDomain";
CPCappuccinoErrorDomain = kCFErrorDomainCappuccino;
CPCocoaErrorDomain = kCFErrorDomainCappuccino; // compat
CPUnderlyingErrorKey = @"CPUnderlyingErrorKey";
CPUnderlyingErrorKey = kCFErrorUnderlyingErrorKey;
CPLocalizedDescriptionKey = @"CPLocalizedDescriptionKey";
CPLocalizedFailureReasonErrorKey = @"CPLocalizedFailureReasonErrorKey";
CPLocalizedRecoverySuggestionErrorKey = @"CPLocalizedRecoverySuggestionErrorKey";
CPLocalizedDescriptionKey = kCFErrorLocalizedDescriptionKey;
CPLocalizedFailureReasonErrorKey = kCFErrorLocalizedFailureReasonKey;
CPLocalizedRecoverySuggestionErrorKey = kCFErrorLocalizedRecoverySuggestionKey;
CPLocalizedRecoveryOptionsErrorKey = @"CPLocalizedRecoveryOptionsErrorKey";
CPRecoveryAttempterErrorKey = @"CPRecoveryAttempterErrorKey";
CPHelpAnchorErrorKey = @"CPHelpAnchorErrorKey";
CPStringEncodingErrorKey = @"CPStringEncodingErrorKey";
CPURLErrorKey = @"CPURLErrorKey";
CPFilePathErrorKey = @"CPFilePathErrorKey";
CPURLErrorKey = kCFErrorURLKey;
CPFilePathErrorKey = kCFErrorFilePathKey;
/*!
@class CPError
@ingroup foundation
@brief Used for encapsulating, presenting, and recovery from errors.
CPError is toll-free bridged with CFError() methods.
An example of initializing a CPError:
<pre>
var userInfo = @{CPLocalizedDescriptionKey: @"A localized error description",
CPLocalizedFailureReasonErrorKey: @"A localized failure reason",
CPUnderlyingErrorKey: @"An underlying error message"},
err = [CPError errorWithDomain:CPCappuccinoErrorDomain code:-10 userInfo:userInfo];
</pre>
*/
@implementation CPError : CPObject
{
CPInteger _code @accessors(property=code, readonly);
CPString _domain @accessors(property=domain, readonly);
CPDictionary _userInfo @accessors(property=userInfo, readonly);
}
+ (id)alloc
{
var obj = new CFError();
obj.isa = [self class];
return obj;
}
+ (id)errorWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict
{
return [[CPError alloc] initWithDomain:aDomain code:aCode userInfo:aDict];
@@ -56,44 +77,94 @@ CPFilePathErrorKey = @"CPFilePathErrorKey";
- (id)initWithDomain:(CPString)aDomain code:(CPInteger)aCode userInfo:(CPDictionary)aDict
{
if (self = [super init])
{
_domain = aDomain;
_code = aCode;
_userInfo = aDict;
}
return self;
var result = new CFError(aDomain, aCode, aDict);
result.isa = [self class];
return result;
}
- (CPInteger)code
{
return self.code();
}
- (CPString)userInfo
{
return self.userInfo();
}
- (CPString)domain
{
return self.domain();
}
/*!
By default this method returns the object in the user info dictionary for the key
CPLocalizedDescriptionKey. If the user info dictionary doesn’t contain a value for
CPLocalizedDescriptionKey, a default string is constructed from the domain and code.
*/
- (CPString)localizedDescription
{
return [_userInfo objectForKey:CPLocalizedDescriptionKey];
return self.description();
}
- (CPString)localizedFailureReason
{
return [_userInfo objectForKey:CPLocalizedFailureReasonErrorKey];
return self.failureReason();
}
- (CPArray)localizedRecoveryOptions
{
return [_userInfo objectForKey:CPLocalizedRecoveryOptionsErrorKey];
var userInfo = self.userInfo(),
recoveryOptions = userInfo.valueForKey(CPLocalizedRecoveryOptionsErrorKey);
return recoveryOptions;
}
- (CPString)localizedRecoverySuggestion
{
return [_userInfo objectForKey:CPLocalizedRecoverySuggestionErrorKey];
return self.recoverySuggestion();
}
- (id)recoveryAttempter
{
return [_userInfo objectForKey:CPRecoveryAttempterErrorKey];
var userInfo = self.userInfo(),
recoveryAttempter = userInfo.valueForKey(CPRecoveryAttempterErrorKey);
return recoveryAttempter;
}
- (CPString)description
{
return [CPString stringWithFormat:@"Error Domain=%@ Code=%d UserInfo=%p %@", _domain, _code, _userInfo, [self localizedDescription]];
return [CPString stringWithFormat:@"Error Domain=%@ Code=%d \"%@\" UserInfo=%@", self.domain(), self.code(), self.description(), self.userInfo()];
}
@end
var CPErrorCodeKey = @"CPErrorCodeKey",
CPErrorDomainKey = @"CPErrorDomainKey",
CPErrorUserInfoKey = @"CPErrorUserInfoKey";
@implementation CPError (CPCoding)
- (id)initWithCoder:(CPCoder)aCoder
{
var code = [aCoder decodeIntForKey:CPErrorCodeKey],
domain = [aCoder decodeObjectForKey:CPErrorDomainKey],
userInfo = [aCoder decodeObjectForKey:CPErrorUserInfoKey];
return [self initWithDomain:domain
code:code
userInfo:userInfo];
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:self.domain() forKey:CPErrorDomainKey];
[aCoder encodeObject:self.code() forKey:CPErrorCodeKey];
[aCoder encodeObject:self.userInfo() forKey:CPErrorUserInfoKey];
}
@end
CFError.prototype.isa = CPError;
+39
View File
@@ -0,0 +1,39 @@
/*
* The CPURL Error Domain
*/
CPURLErrorDomain = @"CPURLErrorDomain";
/*
* CPURL UserInfo Error Keys
*/
CPURLErrorFailingURLErrorKey = @"CPErrorFailingURLKey";
CPURLErrorFailingURLStringErrorKey = @"CPURLErrorFailingURLStringKey";
/*
* CPURL Error Codes
*/
CPURLErrorUnknown = -1;
CPURLErrorCancelled = kCFURLErrorCancelled;
CPURLErrorBadURL = kCFURLErrorBadURL;
CPURLErrorTimedOut = kCFURLErrorTimedOut;
CPURLErrorUnsupportedURL = kCFURLErrorUnsupportedURL;
CPURLErrorCannotFindHost = kCFURLErrorCannotFindHost;
CPURLErrorCannotConnectToHost = kCFURLErrorCannotConnectToHost;
CPURLErrorNetworkConnectionLost = kCFURLErrorNetworkConnectionLost;
CPURLErrorDNSLookupFailed = kCFURLErrorDNSLookupFailed;
CPURLErrorHTTPTooManyRedirects = kCFURLErrorHTTPTooManyRedirects;
CPURLErrorResourceUnavailable = kCFURLErrorResourceUnavailable;
CPURLErrorNotConnectedToInternet = kCFURLErrorNotConnectedToInternet;
CPURLErrorRedirectToNonExistentLocation = kCFURLErrorRedirectToNonExistentLocation;
CPURLErrorBadServerResponse = kCFURLErrorBadServerResponse;
CPURLErrorUserCancelledAuthentication = kCFURLErrorUserCancelledAuthentication;
CPURLErrorUserAuthenticationRequired = kCFURLErrorUserAuthenticationRequired;
CPURLErrorZeroByteResource = kCFURLErrorZeroByteResource;
CPURLErrorCannotDecodeRawData = kCFURLErrorCannotDecodeRawData;
CPURLErrorCannotDecodeContentData = kCFURLErrorCannotDecodeContentData;
CPURLErrorCannotParseResponse = kCFURLErrorCannotParseResponse;
CPURLErrorFileDoesNotExist = kCFURLErrorFileDoesNotExist;
CPURLErrorFileIsDirectory = kCFURLErrorFileIsDirectory;
CPURLErrorNoPermissionsToReadFile = kCFURLErrorNoPermissionsToReadFile;
CPURLErrorDataLengthExceedsMaximum = kCFURLErrorDataLengthExceedsMaximum;
+1
View File
@@ -73,6 +73,7 @@
@import "CPUndoManager.j"
@import "CPURL.j"
@import "CPURLConnection.j"
@import "CPURLError.j"
@import "CPURLRequest.j"
@import "CPURLResponse.j"
@import "CPUserDefaults.j"
+164
View File
@@ -0,0 +1,164 @@
/*
* CFError.js
* Objective-J
*
* Created by Andrew Hankinson.
* Copyright 2014, Andrew Hankinson.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
GLOBAL(kCFErrorLocalizedDescriptionKey) = "CPLocalizedDescription";
GLOBAL(kCFErrorLocalizedFailureReasonKey) = "CPLocalizedFailureReason";
GLOBAL(kCFErrorLocalizedRecoverySuggestionKey) = "CPLocalizedRecoverySuggestion";
GLOBAL(kCFErrorDescriptionKey) = "CPDescription";
GLOBAL(kCFErrorUnderlyingErrorKey) = "CPUnderlyingError";
GLOBAL(kCFErrorURLKey) = "CPURL";
GLOBAL(kCFErrorFilePathKey) = "CPFilePath";
// GLOBAL(kCFErrorDomainPOSIX) = "";
// GLOBAL(kCFErrorDomainOSStatus) = "";
// GLOBAL(kCFErrorDomainMach) = "";
GLOBAL(kCFErrorDomainCappuccino) = "CPCappuccinoErrorDomain";
GLOBAL(kCFErrorDomainCocoa) = kCFErrorDomainCappuccino;
GLOBAL(CFError) = function(/* CFString */ domain, /* int */ code, /* CFDictionary */ userInfo)
{
this._domain = domain || NULL;
this._code = code || 0;
this._userInfo = userInfo || new CFDictionary();
this._UID = objj_generateObjectUID();
};
CFError.prototype.domain = function()
{
return this._domain;
};
DISPLAY_NAME(CFError.prototype.domain);
CFError.prototype.code = function()
{
return this._code;
};
DISPLAY_NAME(CFError.prototype.code);
/*
This follows the same logic to generate a description as the "real" CFError.
*/
CFError.prototype.description = function()
{
var localizedDesc = this._userInfo.valueForKey(kCFErrorLocalizedDescriptionKey);
if (localizedDesc)
return localizedDesc;
var reason = this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey);
if (reason)
{
var operationFailedStr = "The operation couldn\u2019t be completed. " + reason;
return operationFailedStr;
}
// @TODO Add the bundle localized domain handler.
var result = "",
desc = this._userInfo.valueForKey(kCFErrorDescriptionKey);
if (desc)
{
// we have a description key.
var result = "The operation couldn\u2019t be completed. (error " + this._code + " - " + desc + ")";
}
else
{
// just use error and code;
var result = "The operation couldn\u2019t be completed. (error " + this._code + ")";
}
return result;
};
DISPLAY_NAME(CFError.prototype.description);
CFError.prototype.failureReason = function()
{
return this._userInfo.valueForKey(kCFErrorLocalizedFailureReasonKey);
};
DISPLAY_NAME(CFError.prototype.failureReason);
CFError.prototype.recoverySuggestion = function()
{
return this._userInfo.valueForKey(kCFErrorLocalizedRecoverySuggestionKey);
};
DISPLAY_NAME(CFError.prototype.recoverySuggestion);
CFError.prototype.userInfo = function ()
{
return this._userInfo;
};
DISPLAY_NAME(CFError.prototype.userInfo);
/*
CFError Bridge Functions
The "Create" and "Copy" in the function names do not have any meaning
in Cappuccino; they are bridged here for compatibility reasons only.
*/
GLOBAL(CFErrorCreate) = function(/* String */ domain, /*int */ code, /* CFDictionary */ userInfo)
{
return new CFError(domain, code, userInfo);
};
GLOBAL(CFErrorCreateWithUserInfoKeysAndValues) = function(/* String */ domain, /* int */ code, /* array */ userInfoKeys, /* array */ userInfoValues, /* int */ numUserInfoValues)
{
var userInfo = new CFMutableDictionary();
while (numUserInfoValues--)
userInfo.setValueForKey(userInfoKeys[numUserInfoValues], userInfoValues[numUserInfoValues]);
return new CFError(domain, code, userInfo);
};
GLOBAL(CFErrorGetCode) = function(/* CFError */ err)
{
return err.code();
};
GLOBAL(CFErrorGetDomain) = function(/* CFError */ err)
{
return err.domain();
};
GLOBAL(CFErrorCopyDescription) = function(/* CFError */ err)
{
return err.description();
};
GLOBAL(CFErrorCopyUserInfo) = function(/* CFError */ err)
{
return err.userInfo();
};
GLOBAL(CFErrorCopyFailureReason) = function(/* CFError */ err)
{
return err.failureReason();
};
GLOBAL(CFErrorCopyRecoverySuggestion) = function(/* CFError */err)
{
return err.recoverySuggestion();
};
+25
View File
@@ -0,0 +1,25 @@
GLOBAL(kCFURLErrorUnknown) = -998;
GLOBAL(kCFURLErrorCancelled) = -999;
GLOBAL(kCFURLErrorBadURL) = -1000;
GLOBAL(kCFURLErrorTimedOut) = -1001;
GLOBAL(kCFURLErrorUnsupportedURL) = -1002;
GLOBAL(kCFURLErrorCannotFindHost) = -1003;
GLOBAL(kCFURLErrorCannotConnectToHost) = -1004;
GLOBAL(kCFURLErrorNetworkConnectionLost) = -1005;
GLOBAL(kCFURLErrorDNSLookupFailed) = -1006;
GLOBAL(kCFURLErrorHTTPTooManyRedirects) = -1007;
GLOBAL(kCFURLErrorResourceUnavailable) = -1008;
GLOBAL(kCFURLErrorNotConnectedToInternet) = -1009;
GLOBAL(kCFURLErrorRedirectToNonExistentLocation) = -1010;
GLOBAL(kCFURLErrorBadServerResponse) = -1011;
GLOBAL(kCFURLErrorUserCancelledAuthentication) = -1012;
GLOBAL(kCFURLErrorUserAuthenticationRequired) = -1013;
GLOBAL(kCFURLErrorZeroByteResource) = -1014;
GLOBAL(kCFURLErrorCannotDecodeRawData) = -1015;
GLOBAL(kCFURLErrorCannotDecodeContentData) = -1016;
GLOBAL(kCFURLErrorCannotParseResponse) = -1017;
GLOBAL(kCFURLErrorRequestBodyStreamExhausted) = -1021;
GLOBAL(kCFURLErrorFileDoesNotExist) = -1100;
GLOBAL(kCFURLErrorFileIsDirectory) = -1101;
GLOBAL(kCFURLErrorNoPermissionsToReadFile) = -1102;
GLOBAL(kCFURLErrorDataLengthExceedsMaximum) = -1103;
+2
View File
@@ -38,6 +38,8 @@
#include "CFHTTPRequest.js"
#include "CFPropertyList.js"
#include "CFDictionary.js"
#include "CFError.js"
#include "CFNetworkErrors.js"
#include "CFData.js"
#include "CFURL.js"
#include "MarkedStream.js"
+43
View File
@@ -0,0 +1,43 @@
@import <Foundation/CPError.j>
@import <OJUnit/OJTestCase.j>
@implementation CPErrorTest : OJTestCase
{
}
- (void)testInstanceInstantiation
{
var err = [[CPError alloc] initWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:nil];
[self assertNotNull:err];
}
- (void)testClassInstantiation
{
var err = [CPError errorWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:nil];
[self assertNotNull:err];
}
- (void)testUserInfoDict
{
var userInfo = @{
CPLocalizedDescriptionKey: @"A localized error description",
CPUnderlyingErrorKey: @"An underlying error",
CPLocalizedFailureReasonErrorKey: @"A localized error reason",
CPLocalizedRecoverySuggestionErrorKey: @"The world is about to explode. You can choose to ignore this.",
CPLocalizedRecoveryOptionsErrorKey: ["Cry", "Ignore"]
},
err = [CPError errorWithDomain:CPCappuccinoErrorDomain
code:-10
userInfo:userInfo];
[self assertNotNull:[err userInfo]];
[self assert:[err localizedDescription] equals:@"A localized error description"];
[self assert:[err localizedRecoveryOptions] equals:["Cry", "Ignore"]];
[self assertNull:[err recoveryAttempter]];
}
@end
+60
View File
@@ -0,0 +1,60 @@
@import <OJUnit/OJTestCase.j>
@implementation CFErrorTest : OJTestCase
- (void)testCreate
{
var err = new CFError();
[self assertNotNull:err];
}
- (void)testCreateWithParams
{
var err = new CFError(kCFErrorDomainCappuccino, -1000, nil);
[self assertNotNull:err];
[self assert:-1000 equals:err.code()];
}
- (void)testCreateGlobal
{
var err = CFErrorCreate(kCFErrorDomainCappuccino, -1000, nil);
[self assertNotNull:err];
[self assert:kCFErrorDomainCappuccino equals:err.domain()];
[self assert:-1000 equals:err.code()];
[self assert:@"CPCappuccinoErrorDomain" equals:CFErrorGetDomain(err)];
}
- (void)testCreateWithUserInfoKeysAndValues
{
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey, kCFErrorDescriptionKey], [@"A localized description", @"An error description"], 2);
[self assertNotNull:err];
var info = err.userInfo();
[self assert:2 equals:info.count()];
}
- (void)testDescriptionCaseOne
{
// Description case 1: Localized Key set
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedDescriptionKey], [@"A localized Description Key"], 1);
[self assert:@"A localized Description Key" equals:err.description()];
[self assert:@"A localized Description Key" equals:CFErrorCopyDescription(err)];
}
- (void)testDescriptionCaseTwo
{
// Case 2: Reason set; description generated
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorLocalizedFailureReasonKey], [@"A localized reason"], 1);
[self assert:@"The operation couldn\u2019t be completed. A localized reason" equals:err.description()];
}
- (void)testDescriptionCaseThree
{
// Case 3: Final fall-back.
var err = CFErrorCreateWithUserInfoKeysAndValues(kCFErrorDomainCappuccino, -1000, [kCFErrorDescriptionKey], [@"A description key"], 1);
[self assert:@"The operation couldn\u2019t be completed. (error -1000 - A description key)" equals:err.description()];
}
@end