Skip to content

Commit a52403f

Browse files
committed
Option parsing fixes:
1. If a flag has an unexpected suffix and is not supported by the current driver mode, diagnose it as an unsupported option instead of being available in another mode 2. Reject 'separate' options if they have an unexpected suffix
1 parent 96cd66d commit a52403f

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

Sources/SwiftOptions/OptionParsing.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,13 @@ extension OptionTable {
7676
index: index - 1, argument: argument)
7777
}
7878

79-
// Make sure this option is supported by the current driver kind.
80-
guard option.isAccepted(by: driverKind) else {
81-
throw OptionParseError.unsupportedOption(
82-
index: index - 1, argument: argument, option: option,
83-
currentDriverKind: driverKind)
79+
let verifyOptionIsAcceptedByDriverKind = {
80+
// Make sure this option is supported by the current driver kind.
81+
guard option.isAccepted(by: driverKind) else {
82+
throw OptionParseError.unsupportedOption(
83+
index: index - 1, argument: argument, option: option,
84+
currentDriverKind: driverKind)
85+
}
8486
}
8587

8688
// Translate the argument
@@ -90,6 +92,7 @@ extension OptionTable {
9092

9193
case .commaJoined:
9294
// Comma-separated list of arguments follows the option spelling.
95+
try verifyOptionIsAcceptedByDriverKind()
9396
let rest = argument.dropFirst(option.spelling.count)
9497
parsedOptions.addOption(
9598
option,
@@ -101,16 +104,19 @@ extension OptionTable {
101104
throw OptionParseError.unknownOption(
102105
index: index - 1, argument: argument)
103106
}
107+
try verifyOptionIsAcceptedByDriverKind()
104108
parsedOptions.addOption(option, argument: .none)
105109

106110
case .joined:
107111
// Argument text follows the option spelling.
112+
try verifyOptionIsAcceptedByDriverKind()
108113
parsedOptions.addOption(
109114
option,
110115
argument: .single(String(argument.dropFirst(option.spelling.count))))
111116

112117
case .joinedOrSeparate:
113118
// Argument text follows the option spelling.
119+
try verifyOptionIsAcceptedByDriverKind()
114120
let arg = argument.dropFirst(option.spelling.count)
115121
if !arg.isEmpty {
116122
parsedOptions.addOption(option, argument: .single(String(arg)))
@@ -131,6 +137,12 @@ extension OptionTable {
131137
index = arguments.endIndex
132138

133139
case .separate:
140+
if argument != option.spelling {
141+
throw OptionParseError.unknownOption(
142+
index: index - 1, argument: argument)
143+
}
144+
try verifyOptionIsAcceptedByDriverKind()
145+
134146
if index == arguments.endIndex {
135147
throw OptionParseError.missingArgument(
136148
index: index - 1, argument: argument)

Tests/SwiftOptionsTests/OptionParsingTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ final class SwiftDriverTests: XCTestCase {
3232
XCTAssertEqual(error as? OptionParseError, .unknownOption(index: 0, argument: "-unrecognized"))
3333
}
3434

35+
// Ensure we check for an unexpected suffix on flags before checking if they are accepted by the current mode.
36+
XCTAssertThrowsError(try options.parse(["-c-NOT"], for: .interactive)) { error in
37+
XCTAssertEqual(error as? OptionParseError, .unknownOption(index: 0, argument: "-c-NOT"))
38+
}
39+
40+
XCTAssertThrowsError(try options.parse(["-module-name-NOT", "foo"], for: .batch)) { error in
41+
XCTAssertEqual(error as? OptionParseError, .unknownOption(index: 0, argument: "-module-name-NOT"))
42+
}
43+
3544
XCTAssertThrowsError(try options.parse(["-I"], for: .batch)) { error in
3645
XCTAssertEqual(error as? OptionParseError, .missingArgument(index: 0, argument: "-I"))
3746
}

0 commit comments

Comments
 (0)