commandlineparser / commandlineparser/commandline

Parameter name is treated as parameter value

Open
#857 4 comments 1 reaction 0 assignees View on GitHub
bug help wanted
Dominant language
C#
Stars
4.8k
Forks
478
PR merge metrics
No merged PRs in 30d

Description

If I omit parameter value for one parameter name, next parametername is treated as value of the parameter.
Occurred at v2.9.1 from Nuget.

### What I observed
Code:
```
using System;
using CommandLine;

class Options
{
[Option('a', "option1", Required = true)]
public string Option1 { get; set; }

[Option('b', "option2", Required = false)]
public int option2 { get; set; }
}

class Program
{
static int Main(string[] args)
{
return Parser.Default.ParseArguments(args)
.MapResult(
options => RunAndReturnExitCode(options),
_ => -1);
}

static int RunAndReturnExitCode(Options options)
{
Console.WriteLine($"option1={options.Option1}, option2={options.option2}");
return 0;
}
}
```
Command line,
`$command --option1 --option2 5`
gives the result output,
`option1=option2, option2=0`

But expected result is to report error with lacking of required "option1".

### Suggested fix
In the method "CommandLine.Core.TokenPartitioner.PartitionTokensByType", scalarTokens.add(Scalar nem token) shall be occurred only when the following value is confirmed.

```
public static Tuple, IEnumerable, IEnumerable, IEnumerable> PartitionTokensByType(
IEnumerable tokens,
Func> typeLookup)
{
var switchTokens = new List();
var scalarTokens = new List();
var sequenceTokens = new List();
var nonOptionTokens = new List();
var sequences = new Dictionary>();
var count = new Dictionary();
var max = new Dictionary>();
var state = SequenceState.TokenSearch;
var separatorSeen = false;
Token nameToken = null;
foreach (var token in tokens)
{
if (token.IsValueForced())
{
separatorSeen = false;
nonOptionTokens.Add(token);
}
else if (token.IsName())
{
separatorSeen = false;
if (typeLookup(token.Text).MatchJust(out var info))
{
switch (info.TargetType)
{
case TargetType.Switch:
nameToken = null;
switchTokens.Add(token);
state = SequenceState.TokenSearch;
break;
case TargetType.Scalar:
nameToken = token;
// scalarTokens.Add(nameToken); <- don't add here
state = SequenceState.ScalarTokenFound;
break;
case TargetType.Sequence:
nameToken = token;
if (! sequences.ContainsKey(nameToken))
{
sequences[nameToken] = new List();
count[nameToken] = 0;
max[nameToken] = info.MaxItems;
}
state = SequenceState.SequenceTokenFound;
break;
}
}
else
{
nameToken = null;
nonOptionTokens.Add(token);
state = SequenceState.TokenSearch;
}
}
else
{
switch (state)
{
case SequenceState.TokenSearch:
case SequenceState.ScalarTokenFound when nameToken == null:
case SequenceState.SequenceTokenFound when nameToken == null:
separatorSeen = false;
nameToken = null;
nonOptionTokens.Add(token);
state = SequenceState.TokenSearch;
break;

case SequenceState.ScalarTokenFound:
separatorSeen = false;
scalarTokens.Add(nameToken); // add here instead so that scalar name token is valid only when a value is given
nameToken = null;
scalarTokens.Add(token);
state = SequenceState.TokenSearch;
break;

......
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.