apple / apple/swift-argument-parser
Incorrect error message for .allRemainingInput options without values
- Dominant language
- Swift
- Stars
- 3.8k
- Forks
- 411
- Avg merge
- 7d 14h
- Merged PRs (30d)
- 15
Description
Issue #434 reported that when a label, but no values, are provided for an array `@Option` property, the error message incorrectly signifies a missing option instead of a missing value. PR #435 fixed this for `.upToNextOption` arrays, but the bug remained for `.allRemainingInput` arrays.
### Example
```swift
@main
struct Example: ParsableCommand {
@Option(parsing: .remaining)
var test: [String]
mutating func run() throws {
print(test)
}
}
```
### Expected Behaviour
```
$ example --test
Error: Missing value for '--test '
```
### Actual Behaviour
```
$ example --test
Error: Missing expected argument '--test ...'
```
### Unexpected Side-Effect
I created a commit that fixes this issue for `.allRemainingInput` arrays at james-fletcher-01@1bf93bfcf8f597deb885ffe0ef7554a59f9b81f2. However, this change breaks the following test:
```swift
func testParsing_repeatingStringRemaining_2() {
AssertParse(Baz.self, ["--names"]) { baz in
XCTAssertFalse(baz.verbose)
XCTAssertTrue(baz.names.isEmpty)
}
}
```
This implies that for options with a default value, the expected behavior is for an option label without a value to essentially be ignored and retain the default value. For example, while the above test uses an empty array as the default value, this works as well:
```swift
struct NonEmptyDefaultValue: ParsableArguments {
@Option(parsing: .remaining)
var names = ["default"]
}
func testNonEmptyDefaultValue() {
AssertParse(NonEmptyDefaultValue.self, ["--names"]) { baz in
XCTAssertEqual(baz.names, ["default"])
}
}
```
It's surprising to me that this would be the expected behaviour.
- No other parsing strategy accepts an option label without a value. This includes single values strategies, as well as `.upToNextOption`.
- In the example where the default is an empty array, it kind of makes sense. But the example I provided above seems especially counter-intuitive, since you explicitly provided an "empty option" but ended up with a non-empty value.
So if this really is expected behaviour, I can modify my changes to detect the presence of a default value and supress the error message before I submit a PR. But I would just like to get others' thoughts on this?
**ArgumentParser version:** `main`
**Swift version: swift-driver version:** 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1)
### Checklist
- [x] If possible, I've reproduced the issue using the `main` branch of this package
- [X] I've searched for [existing GitHub issues](https://github.com/apple/swift-argument-parser/issues)
Contributor guide
Research direction
Start with testParsing_repeatingStringRemaining_2 and testNonEmptyDefaultValue, then trace the .allRemainingInput/.remaining option parsing path. Compare its missing-value handling with .upToNextOption and the behavior described in the examples. Done means the expected behavior for an option label without a value is decided and covered by tests without regressing default values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100