- Notifications
You must be signed in to change notification settings - Fork 286
Closed
Description
Example:
class SameOptionAndPosValueArgs{[Option('u', "unit")] public string OptValue{get; set} [Value(0)] public string PosValue{get; set} } [Fact] public void SameOptionAndPosValue(){var parser = Parser.Default; var result = parser.ParseArguments<SameOptionAndPosValueArgs>( new[]{"arg", "-u", "arg" }); // !!! pos and value are "arg" result .WithNotParsed(errors =>{throw new InvalidOperationException("Must be parsed.")}) .WithParsed(args =>{Assert.Equal("arg", args.OptValue); Assert.Equal("arg", args.PosValue); // !!! args.PosValue is null })} When user enters same values for [Option] and [Value] args, parser is losing one of it because they are equal tokens.
TokenPartitioner.cs has code:
var nonOptions = tokenList .Where(t => !switches.Contains(t)) .Where(t => !scalars.Contains(t)) .Where(t => !sequences.Contains(t)).Memorize(); var values = nonOptions.Where(v => v.IsValue()).Memorize(); var errors = nonOptions.Except(values).Memorize(); One of tokens for "-u" option is already in scalars variable so Where is filtering out both tokens with "arg" and then its not gettings into values. Filtering is happening because all tokens classes have IEqualtable<T> so "arg" == "arg" but it is two different items in memory.
One of solutions: make reference comparing, not IEqutable<T>. .Net doesn't have such comparer. Stackoverflow helps:
internal sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer<object>{public static readonly ReferenceEqualityComparer Default = new ReferenceEqualityComparer(); public new bool Equals(object x, object y){return x == y; // reference equality because operator== is static and resolved at compile-time } public int GetHashCode(object obj){return RuntimeHelpers.GetHashCode(obj)} } Pass this comparer to Contains and Except:
var nonOptions = tokenList .Where(t => !switches.Contains(t, ReferenceEqualityComparer.Default)) .Where(t => !scalars.Contains(t, ReferenceEqualityComparer.Default)) .Where(t => !sequences.Contains(t, ReferenceEqualityComparer.Default)).Memorize(); var values = nonOptions.Where(v => v.IsValue()).Memorize(); var errors = nonOptions.Except(values, ReferenceEqualityComparer.Default).Cast<Token>().Memorize(); Metadata
Metadata
Assignees
Labels
No labels