Skip to content

Commit 53555a0

Browse files
Support Exit codes from thrown CustomNSError conformers (#244)
Introduce customnserror support, so exit code is calculated correctly, resolves #243.
1 parent d633b43 commit 53555a0

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

Sources/ArgumentParser/Usage/MessageInfo.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ enum MessageInfo {
6262
self.init(error: CommandError(commandStack: [type.asCommand], parserError: e), type: type)
6363
return
6464

65+
case let e as CustomNSError:
66+
// Send CustomNSError back through the CommandError path
67+
self.init(
68+
error: CommandError(
69+
commandStack: [type.asCommand],
70+
parserError: .userValidationError(e)
71+
),
72+
type: type
73+
)
74+
return
75+
6576
default:
6677
commandStack = [type.asCommand]
6778
// if the error wasn't one of our two Error types, wrap it as a userValidationError
@@ -92,6 +103,8 @@ enum MessageInfo {
92103
}
93104
case let error as ExitCode:
94105
self = .other(message: "", exitCode: error.rawValue)
106+
case let error as CustomNSError:
107+
self = .other(message: error.localizedDescription, exitCode: Int32(error.errorCode))
95108
case let error as LocalizedError where error.errorDescription != nil:
96109
self = .other(message: error.errorDescription!, exitCode: EXIT_FAILURE)
97110
default:

Tests/ArgumentParserUnitTests/ExitCodeTests.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,53 @@ extension ExitCodeTests {
7676
}
7777
}
7878
}
79+
80+
// MARK: - CustomNSError tests
81+
82+
extension ExitCodeTests {
83+
enum MyCustomNSError: CustomNSError {
84+
case myFirstCase
85+
case mySecondCase
86+
87+
var errorCode: Int {
88+
switch self {
89+
case .myFirstCase:
90+
return 101
91+
case .mySecondCase:
92+
return 102
93+
}
94+
}
95+
96+
var errorUserInfo: [String : Any] {
97+
switch self {
98+
case .myFirstCase:
99+
return [NSLocalizedDescriptionKey: "My first case localized description"]
100+
case .mySecondCase:
101+
return [:]
102+
}
103+
}
104+
}
105+
106+
struct CheckFirstCustomNSErrorCommand: ParsableCommand {
107+
108+
@Option
109+
var errorCase: Int
110+
111+
func run() throws {
112+
switch errorCase {
113+
case 101:
114+
throw MyCustomNSError.myFirstCase
115+
default:
116+
throw MyCustomNSError.mySecondCase
117+
}
118+
}
119+
}
120+
121+
func testCustomErrorCodeForTheFirstCase() {
122+
XCTAssertEqual(CheckFirstCustomNSErrorCommand.exitCode(for: MyCustomNSError.myFirstCase), ExitCode(rawValue: 101))
123+
}
124+
125+
func testCustomErrorCodeForTheSecondCase() {
126+
XCTAssertEqual(CheckFirstCustomNSErrorCommand.exitCode(for: MyCustomNSError.mySecondCase), ExitCode(rawValue: 102))
127+
}
128+
}

0 commit comments

Comments
 (0)