apple / apple/swift-argument-parser

Option not being parsed correctly

Open
#371 0 comments 1 reaction 0 assignees View on GitHub
bug
Dominant language
Swift
Stars
3.8k
Forks
411
Avg merge
7d 14h
Merged PRs (30d)
15

Description

The Argument Parser isn't able to parse an `Option` correctly in a very specific parameter setting (see example below). This may even result in wrongly parsed values.

**ArgumentParser version:** `1.0.1`
**Swift version:** `swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: x86_64-apple-macosx12.0`

### Steps to Reproduce
The Argument Parser isn't able to parse an `Option` correctly if it is stated between a "normal" `Argument` and an `Argument` with the `unconditionalRemaining` setting.

Here an example:
```swift
struct ExampleCommand: ParsableCommand {
@Argument(help: "Works as expected")
var firstArg: String

@Option(help: "Not recognized argument")
var secondArg: String

@Argument(parsing: .unconditionalRemaining, help:"Failure causing argument, especially the `unconditionalRemaining` option")
var thirdArg: [String]
}
```

`swift run ArgumentParserExample --help` prints the following (for all tested swift-argument-parser versions, so v0.4.4 onwards):
```
OVERVIEW: Example Command that showcases bug in the swift-argument-parser

USAGE: example-command --second-arg [ ...]

ARGUMENTS:
Works as expected
Failure causing argument, especially the `unconditionalRemaining` option

OPTIONS:
--second-arg
Not recognized argument
--version Show the version.
-h, --help Show help information.
```

A related run Command could look like the following: `swift run ArgumentParserExample test1 --second-arg=test2 test3 --test4 -t`

**[Repository](https://github.com/philippzagar/swift-argument-parser-bug-example)** containing example code reproducing the behavior described below. Try the different swift-argument-parser versions in the `Package.swift` file.

### Expected behavior
One would expect that all stated CLI parameters are parsed correctly and that they can be accessed containing the correct values.
Especially, the `secondArg` parameter ( --second-arg ) is detected and parsed correctly.
Occurs correctly on v0.4.4 of the swift-argument-parser.

However, the `thirdArg` actually contains the `--second-arg=test2` from the run CMD mentioned above. This shouldn't be the case, as only the `secondArg` should contain the correct value (`test2`), which it also does in this scenario.

### Actual behavior
Starting with the swift-argument-parser v0.5 and up until the current v1.0.1 version, the parsing fails with the error message that the `secondArg` is missing (again, using the run CMD mentioned above):
```
Error: Missing expected argument '--second-arg '
Help: --second-arg Not recognized argument
Usage: example-command --second-arg [ ...]
See 'example-command --help' for more information.
```

Setting the name of the `Option` explicitly to `second-arg` (so `--second-arg`) within the initialization of the `Option` property wrapper doesn't change the behavior.

As soon as the `unconditionalRemaining` option for the last `Argument` is deleted, the parsing is done correctly, under the condition that the passed parameters after the `--second-arg` are not `Option`'s on their own (so no `--test4` or `-t` anymore). Same behavior as soon as the first `Argument` (so `firstArg`) is deleted.
As described in the example above, the `secondArg` parameter ( --second-arg ) isn't being detected correctly.

It seems to me that the `.unconditionalRemaining` option to a certain extent is responsible for this incorrect behavior. However, as mentioned above, if the `firstArg` is deleted, the parsing is done correctly, even with the `.unconditionalRemaining` option (even with correct values of the parsed parameters!).

Contributor guide

Open the contributing guide

Research direction

Start with the linked reproduction repository and its Package.swift, then run the reported command while comparing swift-argument-parser v0.4.4 with v0.5 and v1.0.1. Trace how the firstArg, secondArg, and unconditionalRemaining thirdArg are parsed; done means --second-arg receives test2 and the remaining values do not incorrectly include that option.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.