diff --git a/src/CommandLine/CommandLine.csproj b/src/CommandLine/CommandLine.csproj index b5bdb6ff..7b791726 100644 --- a/src/CommandLine/CommandLine.csproj +++ b/src/CommandLine/CommandLine.csproj @@ -84,6 +84,7 @@ + diff --git a/src/CommandLine/Core/TokenPartitioner.cs b/src/CommandLine/Core/TokenPartitioner.cs index 75919cc8..ebe6c0ca 100644 --- a/src/CommandLine/Core/TokenPartitioner.cs +++ b/src/CommandLine/Core/TokenPartitioner.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using CommandLine.Infrastructure; using CSharpx; namespace CommandLine.Core @@ -23,11 +24,11 @@ public static var scalars = Scalar.Partition(tokenList, typeLookup).Memorize(); var sequences = Sequence.Partition(tokenList, typeLookup).Memorize(); var nonOptions = tokenList - .Where(t => !switches.Contains(t)) - .Where(t => !scalars.Contains(t)) - .Where(t => !sequences.Contains(t)).Memorize(); + .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).Memorize(); + var errors = nonOptions.Except(values, (IEqualityComparer)ReferenceEqualityComparer.Default).Memorize(); return Tuple.Create( KeyValuePairHelper.ForSwitch(switches) diff --git a/src/CommandLine/Infrastructure/ReferenceEqualityComparer.cs b/src/CommandLine/Infrastructure/ReferenceEqualityComparer.cs new file mode 100644 index 00000000..2f6f4c2c --- /dev/null +++ b/src/CommandLine/Infrastructure/ReferenceEqualityComparer.cs @@ -0,0 +1,24 @@ +// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace CommandLine.Infrastructure +{ + internal sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer + { + public static readonly ReferenceEqualityComparer Default = new ReferenceEqualityComparer(); + + public new bool Equals(object x, object y) + { + return ReferenceEquals(x, y); + } + + public int GetHashCode(object obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } +} diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index 0d6213ed..eb6e691e 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -60,6 +60,7 @@ + diff --git a/tests/CommandLine.Tests/Fakes/Options_With_Option_And_Value_Of_String_Type.cs b/tests/CommandLine.Tests/Fakes/Options_With_Option_And_Value_Of_String_Type.cs new file mode 100644 index 00000000..a5ee7d54 --- /dev/null +++ b/tests/CommandLine.Tests/Fakes/Options_With_Option_And_Value_Of_String_Type.cs @@ -0,0 +1,16 @@ +// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. + +using System; +using System.Linq; + +namespace CommandLine.Tests.Fakes +{ + class Options_With_Option_And_Value_Of_String_Type + { + [Option('o', "opt")] + public string OptValue { get; set; } + + [Value(0)] + public string PosValue { get; set; } + } +} diff --git a/tests/CommandLine.Tests/Fakes/Verb_Fakes.cs b/tests/CommandLine.Tests/Fakes/Verb_Fakes.cs index 8f863af0..133c65b5 100644 --- a/tests/CommandLine.Tests/Fakes/Verb_Fakes.cs +++ b/tests/CommandLine.Tests/Fakes/Verb_Fakes.cs @@ -75,4 +75,14 @@ class Derived_Verb : Base_Class_For_Verb HelpText = "Allow adding otherwise ignored files.")] public bool Force { get; set; } } + + [Verb("test")] + class Verb_With_Option_And_Value_Of_String_Type + { + [Option('o', "opt")] + public string OptValue { get; set; } + + [Value(0)] + public string PosValue { get; set; } + } } \ No newline at end of file diff --git a/tests/CommandLine.Tests/Unit/ParserTests.cs b/tests/CommandLine.Tests/Unit/ParserTests.cs index 76426887..19a45d0a 100644 --- a/tests/CommandLine.Tests/Unit/ParserTests.cs +++ b/tests/CommandLine.Tests/Unit/ParserTests.cs @@ -805,6 +805,35 @@ public class NullDefaultCommandLineArguments } [Fact] + public void Parse_options_with_same_option_and_value_args() + { + var parser = Parser.Default; + parser.ParseArguments( + new[] { "arg", "-o", "arg" }) + .WithNotParsed(errors => { throw new InvalidOperationException("Must be parsed."); }) + .WithParsed(args => + { + Assert.Equal("arg", args.OptValue); + Assert.Equal("arg", args.PosValue); + }); + } + + [Fact] + public void Parse_verb_with_same_option_and_value_args() + { + var parser = Parser.Default; + var result = parser.ParseArguments( + new[] { "test", "arg", "-o", "arg" }, + typeof(Verb_With_Option_And_Value_Of_String_Type)); + result + .WithNotParsed(errors => { throw new InvalidOperationException("Must be parsed."); }) + .WithParsed(args => + { + Assert.Equal("arg", args.OptValue); + Assert.Equal("arg", args.PosValue); + }); + } + public void Parse_options_with_shuffled_index_values() { var parser = Parser.Default;