From 919bfda116d2d9416b32516bbd12214572825bea Mon Sep 17 00:00:00 2001 From: Dan Nemec Date: Wed, 8 Jun 2016 16:09:56 -0500 Subject: [PATCH 01/26] Add note on .Net Core support --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4a7a5f7c..6387fa5b 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Compatibility: --- - .NET Framework 4.0+ - Mono 2.1+ Profile + - .Net Core - Note: support for Core is currently limited to an [alternate branch](https://github.com/gsscoder/commandline/tree/dotnet-core) while we wait for release of 1.0. If you have suggestions or changes for support of .Net Core, please submit a pull request to that branch until it's merged into master. Current Release: --- From dbc6cc044572abe900d62464cc804a8251bb8577 Mon Sep 17 00:00:00 2001 From: "Rodney S. Foley" Date: Tue, 14 Jun 2016 09:49:33 -0700 Subject: [PATCH 02/26] Defaults to current consoles width if available otherwise uses default. Made easier to override by bring it up to the ParserSettings class. Added ParserSettings.MaximumDisplayWidth property that will be passed to HelpText Added maxDisplayWidth params to several methods with a default of DefaultMaximumLength if not provided Added an attempt to set the MaximumDisplayWidth in ParserSettings and HelpText to Console.WindowWidth and if it isn't possible use MaximumDisplayWidth instead. --- src/CommandLine/Parser.cs | 7 +-- src/CommandLine/ParserSettings.cs | 20 ++++++++ src/CommandLine/Text/HelpText.cs | 35 +++++++++---- .../Unit/Text/HelpTextTests.cs | 50 ++++++++++++++++++- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/src/CommandLine/Parser.cs b/src/CommandLine/Parser.cs index f2cae77b..69a7e862 100644 --- a/src/CommandLine/Parser.cs +++ b/src/CommandLine/Parser.cs @@ -187,15 +187,16 @@ private static ParserResult MakeParserResult(ParserResult parserResult, { return DisplayHelp( parserResult, - settings.HelpWriter); + settings.HelpWriter, + settings.MaximumDisplayWidth); } - private static ParserResult DisplayHelp(ParserResult parserResult, TextWriter helpWriter) + private static ParserResult DisplayHelp(ParserResult parserResult, TextWriter helpWriter, int maxDisplayWidth) { parserResult.WithNotParsed( errors => Maybe.Merge(errors.ToMaybe(), helpWriter.ToMaybe()) - .Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult))) + .Do((_, writer) => writer.Write(HelpText.AutoBuild(parserResult, maxDisplayWidth))) ); return parserResult; diff --git a/src/CommandLine/ParserSettings.cs b/src/CommandLine/ParserSettings.cs index 1777f05f..5e2eb895 100644 --- a/src/CommandLine/ParserSettings.cs +++ b/src/CommandLine/ParserSettings.cs @@ -13,6 +13,8 @@ namespace CommandLine /// public class ParserSettings : IDisposable { + private const int DefaultMaximumLength = 80; // default console width + private bool disposed; private bool caseSensitive; private bool caseInsensitiveEnumValues; @@ -20,6 +22,7 @@ public class ParserSettings : IDisposable private bool ignoreUnknownArguments; private CultureInfo parsingCulture; private bool enableDashDash; + private int maximumDisplayWidth; /// /// Initializes a new instance of the class. @@ -29,6 +32,14 @@ public ParserSettings() caseSensitive = true; caseInsensitiveEnumValues = false; parsingCulture = CultureInfo.InvariantCulture; + try + { + maximumDisplayWidth = Console.WindowWidth; + } + catch (IOException) + { + maximumDisplayWidth = DefaultMaximumLength; + } } /// @@ -114,6 +125,15 @@ public bool EnableDashDash set { PopsicleSetter.Set(Consumed, ref enableDashDash, value); } } + /// + /// Gets or sets the maximum width of the display. This determines word wrap when displaying the text. + /// + public int MaximumDisplayWidth + { + get { return maximumDisplayWidth; } + set { maximumDisplayWidth = value; } + } + internal StringComparer NameComparer { get diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 8319094c..037216a0 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -3,6 +3,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Text; using System.Linq; using System.Reflection; @@ -23,7 +24,7 @@ public class HelpText private readonly StringBuilder preOptionsHelp; private readonly StringBuilder postOptionsHelp; private readonly SentenceBuilder sentenceBuilder; - private int? maximumDisplayWidth; + private int maximumDisplayWidth; private string heading; private string copyright; private bool additionalNewLineAfterOption; @@ -101,7 +102,14 @@ public HelpText(SentenceBuilder sentenceBuilder, string heading, string copyrigh preOptionsHelp = new StringBuilder(BuilderCapacity); postOptionsHelp = new StringBuilder(BuilderCapacity); - + try + { + maximumDisplayWidth = Console.WindowWidth; + } + catch (IOException) + { + maximumDisplayWidth = DefaultMaximumLength; + } this.sentenceBuilder = sentenceBuilder; this.heading = heading; this.copyright = copyright; @@ -143,7 +151,7 @@ public string Copyright /// The maximum width of the display. public int MaximumDisplayWidth { - get { return maximumDisplayWidth.HasValue ? maximumDisplayWidth.Value : DefaultMaximumLength; } + get { return maximumDisplayWidth; } set { maximumDisplayWidth = value; } } @@ -193,18 +201,22 @@ public SentenceBuilder SentenceBuilder /// A delegate used to customize the text block of reporting parsing errors text block. /// A delegate used to customize model used to render text block of usage examples. /// If true the output style is consistent with verb commands (no dashes), otherwise it outputs options. + /// The maximum width of the display. /// The parameter is not ontly a metter of formatting, it controls whether to handle verbs or options. public static HelpText AutoBuild( ParserResult parserResult, Func onError, Func onExample, - bool verbsIndex = false) + bool verbsIndex = false, + int maxDisplayWidth = DefaultMaximumLength) { - var auto = new HelpText { + var auto = new HelpText + { Heading = HeadingInfo.Default, Copyright = CopyrightInfo.Default, AdditionalNewLineAfterOption = true, - AddDashesToOption = !verbsIndex + AddDashesToOption = !verbsIndex, + MaximumDisplayWidth = maxDisplayWidth }; var errors = Enumerable.Empty(); @@ -253,12 +265,13 @@ public static HelpText AutoBuild( /// automatically handling verbs or options scenario. /// /// The containing the instance that collected command line arguments parsed with class. + /// The maximum width of the display. /// /// An instance of class. /// /// This feature is meant to be invoked automatically by the parser, setting the HelpWriter property /// of . - public static HelpText AutoBuild(ParserResult parserResult) + public static HelpText AutoBuild(ParserResult parserResult, int maxDisplayWidth = DefaultMaximumLength) { if (parserResult.Tag != ParserResultType.NotParsed) throw new ArgumentException("Excepting NotParsed type.", "parserResult"); @@ -266,16 +279,16 @@ public static HelpText AutoBuild(ParserResult parserResult) var errors = ((NotParsed)parserResult).Errors; if (errors.Any(e => e.Tag == ErrorType.VersionRequestedError)) - return new HelpText(HeadingInfo.Default).AddPreOptionsLine(Environment.NewLine); + return new HelpText(HeadingInfo.Default){MaximumDisplayWidth = maxDisplayWidth }.AddPreOptionsLine(Environment.NewLine); if (!errors.Any(e => e.Tag == ErrorType.HelpVerbRequestedError)) - return AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e); + return AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, maxDisplayWidth: maxDisplayWidth); var err = errors.OfType().Single(); var pr = new NotParsed(TypeInfo.Create(err.Type), Enumerable.Empty()); return err.Matched - ? AutoBuild(pr, current => DefaultParsingErrorsHandler(pr, current), e => e) - : AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, true); + ? AutoBuild(pr, current => DefaultParsingErrorsHandler(pr, current), e => e, maxDisplayWidth: maxDisplayWidth) + : AutoBuild(parserResult, current => DefaultParsingErrorsHandler(parserResult, current), e => e, true, maxDisplayWidth); } /// diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 98eb5302..4c5defe0 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -131,7 +131,7 @@ public void When_defined_MetaValue_should_be_rendered() } [Fact] - public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_column() + public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_column_given_width_of_40() { // Fixture setup // Exercize system @@ -153,6 +153,28 @@ public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_c // Teardown } + + + [Fact] + public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_column_given_width_of_100() + { + // Fixture setup + // Exercize system + var sut = new HelpText(new HeadingInfo("CommandLine.Tests.dll", "1.9.4.131")) { MaximumDisplayWidth = 100} ; + //sut.MaximumDisplayWidth = 100; + sut.AddOptions( + new NotParsed( + TypeInfo.Create(typeof(Simple_Options_With_HelpText_Set_To_Long_Description)), + Enumerable.Empty())); + + // Verify outcome + var lines = sut.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + lines[2].ShouldBeEquivalentTo(" v, verbose This is the description of the verbosity to test out the wrapping capabilities of "); //"The first line should have the arguments and the start of the Help Text."); + //string formattingMessage = "Beyond the second line should be formatted as though it's in a column."; + lines[3].ShouldBeEquivalentTo(" the Help Text."); + // Teardown + } + [Fact] public void Long_help_text_without_spaces() { @@ -315,6 +337,32 @@ public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_fo // Teardown } + [Fact] + public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_formatted_text_given_display_width_100() + { + // Fixture setup + var fakeResult = new NotParsed( + TypeInfo.Create(typeof(NullInstance)), + new Error[] + { + new HelpVerbRequestedError("commit", typeof(Commit_Verb), true) + }); + + // Exercize system + var helpText = HelpText.AutoBuild(fakeResult, maxDisplayWidth: 100); + + // Verify outcome + var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray(); + + lines[0].Should().StartWithEquivalent("CommandLine"); + lines[1].Should().StartWithEquivalent("Copyright (c)"); + lines[2].ShouldBeEquivalentTo("-p, --patch Use the interactive patch selection interface to chose which changes to commit."); + lines[3].ShouldBeEquivalentTo("--amend Used to amend the tip of the current branch."); + lines[4].ShouldBeEquivalentTo("-m, --message Use the given message as the commit message."); + lines[5].ShouldBeEquivalentTo("--help Display this help screen."); + // Teardown + } + [Fact] public void Invoke_AutoBuild_for_Verbs_with_unknown_verb_returns_appropriate_formatted_text() { From 4a47661ef5c727a71defd317d1974dc51029fc8d Mon Sep 17 00:00:00 2001 From: "Rodney S. Foley" Date: Wed, 15 Jun 2016 12:52:13 -0700 Subject: [PATCH 03/26] Implemented Hidden Verbs, Options and Values The attribute Hidden has been added to OptionAttribute, ValueAttribute, and VerbAttribute. By default it is false. Changes to support this new attribute so that if hidden it is not visible in the help text, but is still usable if called correctly. If you ask for help on a hidden verb you will get the help displayed but hidden options will still be hidden. Allowing for hidden verbs with not hidden options. Resolves issue #263 --- src/CommandLine/BaseAttribute.cs | 9 ++ src/CommandLine/Core/OptionSpecification.cs | 11 +-- src/CommandLine/Core/Specification.cs | 9 +- .../Core/SpecificationExtensions.cs | 3 +- src/CommandLine/Core/ValueSpecification.cs | 7 +- src/CommandLine/Core/Verb.cs | 12 ++- src/CommandLine/Text/HelpText.cs | 22 +++-- src/CommandLine/VerbAttribute.cs | 9 ++ tests/CommandLine.Tests/Fakes/Help_Fakes.cs | 35 ++++++++ tests/CommandLine.Tests/Unit/ParserTests.cs | 85 +++++++++++++++++++ .../Unit/Text/HelpTextTests.cs | 24 +++++- 11 files changed, 204 insertions(+), 22 deletions(-) diff --git a/src/CommandLine/BaseAttribute.cs b/src/CommandLine/BaseAttribute.cs index a009111d..f91a17a2 100644 --- a/src/CommandLine/BaseAttribute.cs +++ b/src/CommandLine/BaseAttribute.cs @@ -123,5 +123,14 @@ public string MetaValue metaValue = value; } } + + /// + /// Gets or sets a value indicating whether a command line option is visible in the help text. + /// + public bool Hidden + { + get; + set; + } } } diff --git a/src/CommandLine/Core/OptionSpecification.cs b/src/CommandLine/Core/OptionSpecification.cs index e519ffb9..0bbbbb06 100644 --- a/src/CommandLine/Core/OptionSpecification.cs +++ b/src/CommandLine/Core/OptionSpecification.cs @@ -16,8 +16,8 @@ sealed class OptionSpecification : Specification public OptionSpecification(string shortName, string longName, bool required, string setName, Maybe min, Maybe max, char separator, Maybe defaultValue, string helpText, string metaValue, IEnumerable enumValues, - Type conversionType, TargetType targetType) - : base(SpecificationType.Option, required, min, max, defaultValue, helpText, metaValue, enumValues, conversionType, targetType) + Type conversionType, TargetType targetType, bool hidden = false) + : base(SpecificationType.Option, required, min, max, defaultValue, helpText, metaValue, enumValues, conversionType, targetType, hidden) { this.shortName = shortName; this.longName = longName; @@ -40,13 +40,14 @@ public static OptionSpecification FromAttribute(OptionAttribute attribute, Type attribute.MetaValue, enumValues, conversionType, - conversionType.ToTargetType()); + conversionType.ToTargetType(), + attribute.Hidden); } - public static OptionSpecification NewSwitch(string shortName, string longName, bool required, string helpText, string metaValue) + public static OptionSpecification NewSwitch(string shortName, string longName, bool required, string helpText, string metaValue, bool hidden = false) { return new OptionSpecification(shortName, longName, required, string.Empty, Maybe.Nothing(), Maybe.Nothing(), - '\0', Maybe.Nothing(), helpText, metaValue, Enumerable.Empty(), typeof(bool), TargetType.Switch); + '\0', Maybe.Nothing(), helpText, metaValue, Enumerable.Empty(), typeof(bool), TargetType.Switch, hidden); } public string ShortName diff --git a/src/CommandLine/Core/Specification.cs b/src/CommandLine/Core/Specification.cs index 74a09190..cefae158 100644 --- a/src/CommandLine/Core/Specification.cs +++ b/src/CommandLine/Core/Specification.cs @@ -25,6 +25,7 @@ abstract class Specification { private readonly SpecificationType tag; private readonly bool required; + private readonly bool hidden; private readonly Maybe min; private readonly Maybe max; private readonly Maybe defaultValue; @@ -37,7 +38,7 @@ abstract class Specification protected Specification(SpecificationType tag, bool required, Maybe min, Maybe max, Maybe defaultValue, string helpText, string metaValue, IEnumerable enumValues, - Type conversionType, TargetType targetType) + Type conversionType, TargetType targetType, bool hidden = false) { this.tag = tag; this.required = required; @@ -49,6 +50,7 @@ protected Specification(SpecificationType tag, bool required, Maybe min, Ma this.helpText = helpText; this.metaValue = metaValue; this.enumValues = enumValues; + this.hidden = hidden; } public SpecificationType Tag @@ -101,6 +103,11 @@ public TargetType TargetType get { return targetType; } } + public bool Hidden + { + get { return hidden; } + } + public static Specification FromProperty(PropertyInfo property) { var attrs = property.GetCustomAttributes(true); diff --git a/src/CommandLine/Core/SpecificationExtensions.cs b/src/CommandLine/Core/SpecificationExtensions.cs index cad4187f..64e6475a 100644 --- a/src/CommandLine/Core/SpecificationExtensions.cs +++ b/src/CommandLine/Core/SpecificationExtensions.cs @@ -33,7 +33,8 @@ public static OptionSpecification WithLongName(this OptionSpecification specific specification.MetaValue, specification.EnumValues, specification.ConversionType, - specification.TargetType); + specification.TargetType, + specification.Hidden); } public static string UniqueName(this OptionSpecification specification) diff --git a/src/CommandLine/Core/ValueSpecification.cs b/src/CommandLine/Core/ValueSpecification.cs index d898b6db..bd90252e 100644 --- a/src/CommandLine/Core/ValueSpecification.cs +++ b/src/CommandLine/Core/ValueSpecification.cs @@ -13,8 +13,8 @@ sealed class ValueSpecification : Specification public ValueSpecification(int index, string metaName, bool required, Maybe min, Maybe max, Maybe defaultValue, string helpText, string metaValue, IEnumerable enumValues, - Type conversionType, TargetType targetType) - : base(SpecificationType.Value, required, min, max, defaultValue, helpText, metaValue, enumValues, conversionType, targetType) + Type conversionType, TargetType targetType, bool hidden = false) + : base(SpecificationType.Value, required, min, max, defaultValue, helpText, metaValue, enumValues, conversionType, targetType, hidden) { this.index = index; this.metaName = metaName; @@ -33,7 +33,8 @@ public static ValueSpecification FromAttribute(ValueAttribute attribute, Type co attribute.MetaValue, enumValues, conversionType, - conversionType.ToTargetType()); + conversionType.ToTargetType(), + attribute.Hidden); } public int Index diff --git a/src/CommandLine/Core/Verb.cs b/src/CommandLine/Core/Verb.cs index c2c00351..d6c71afc 100644 --- a/src/CommandLine/Core/Verb.cs +++ b/src/CommandLine/Core/Verb.cs @@ -10,14 +10,16 @@ sealed class Verb { private readonly string name; private readonly string helpText; + private readonly bool hidden; - public Verb(string name, string helpText) + public Verb(string name, string helpText, bool hidden = false) { if (name == null) throw new ArgumentNullException("name"); if (helpText == null) throw new ArgumentNullException("helpText"); this.name = name; this.helpText = helpText; + this.hidden = hidden; } public string Name @@ -30,11 +32,17 @@ public string HelpText get { return helpText; } } + public bool Hidden + { + get { return hidden; } + } + public static Verb FromAttribute(VerbAttribute attribute) { return new Verb( attribute.Name, - attribute.HelpText + attribute.HelpText, + attribute.Hidden ); } diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 037216a0..9d29caa6 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -683,7 +683,8 @@ private IEnumerable AdaptVerbsToSpecifications(IEnumerable verbTuple.Item1.Name, false, verbTuple.Item1.HelpText, - string.Empty)).Concat(new[] { MakeHelpEntry(), MakeVersionEntry() }); + string.Empty, + verbTuple.Item1.Hidden)).Concat(new[] { MakeHelpEntry(), MakeVersionEntry() }); } private HelpText AddOptionsImpl( @@ -711,7 +712,8 @@ private OptionSpecification MakeHelpEntry() "help", false, sentenceBuilder.HelpCommandText(AddDashesToOption), - string.Empty); + string.Empty, + false); } private OptionSpecification MakeVersionEntry() @@ -721,7 +723,8 @@ private OptionSpecification MakeVersionEntry() "version", false, sentenceBuilder.VersionCommandText(AddDashesToOption), - string.Empty); + string.Empty, + false); } private HelpText AddPreOptionsLine(string value, int maximumLength) @@ -733,6 +736,9 @@ private HelpText AddPreOptionsLine(string value, int maximumLength) private HelpText AddOption(string requiredWord, int maxLength, Specification specification, int widthOfHelpText) { + if (specification.Hidden) + return this; + optionsHelp.Append(" "); var name = new StringBuilder(maxLength) .BimapIf( @@ -841,13 +847,15 @@ private int GetMaxLength(IEnumerable specifications) { return specifications.Aggregate(0, (length, spec) => - { - var specLength = spec.Tag == SpecificationType.Option + { + if (spec.Hidden) + return length; + var specLength = spec.Tag == SpecificationType.Option ? GetMaxOptionLength((OptionSpecification)spec) : GetMaxValueLength((ValueSpecification)spec); - return Math.Max(length, specLength); - }); + return Math.Max(length, specLength); + }); } diff --git a/src/CommandLine/VerbAttribute.cs b/src/CommandLine/VerbAttribute.cs index 3172f210..af66ac12 100644 --- a/src/CommandLine/VerbAttribute.cs +++ b/src/CommandLine/VerbAttribute.cs @@ -34,6 +34,15 @@ public string Name get { return name; } } + /// + /// Gets or sets a value indicating whether a command line verb is visible in the help text. + /// + public bool Hidden + { + get; + set; + } + /// /// Gets or sets a short description of this command line option. Usually a sentence summary. /// diff --git a/tests/CommandLine.Tests/Fakes/Help_Fakes.cs b/tests/CommandLine.Tests/Fakes/Help_Fakes.cs index 8b7af30a..a35e8599 100644 --- a/tests/CommandLine.Tests/Fakes/Help_Fakes.cs +++ b/tests/CommandLine.Tests/Fakes/Help_Fakes.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using CommandLine.Text; +using Microsoft.FSharp.Collections; namespace CommandLine.Tests.Fakes { @@ -12,6 +13,9 @@ class Simple_Options_Without_HelpText [Option("input-file")] public string FileName { get; set; } + + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } } class Simple_Options_With_HelpText_Set @@ -21,6 +25,9 @@ class Simple_Options_With_HelpText_Set [Option('i', "input-file", Required = true, HelpText = "Specify input file to be processed.")] public string FileName { get; set; } + + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } } class Simple_Options_With_HelpText_Set_To_Long_Description @@ -30,6 +37,9 @@ class Simple_Options_With_HelpText_Set_To_Long_Description [Option("input-file", HelpText = "This is a very long description of the Input File argument that gets passed in. It should be passed in as a string.")] public string FileName { get; set; } + + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } } class Simple_Options_With_HelpText_Set_To_Long_Description_Without_Spaces @@ -39,6 +49,9 @@ class Simple_Options_With_HelpText_Set_To_Long_Description_Without_Spaces [Option("input-file", HelpText = "Before 012345678901234567890123456789 After")] public string FileName { get; set; } + + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } } class Options_With_Usage_Attribute @@ -64,6 +77,9 @@ class Options_With_Usage_Attribute [Value(0, HelpText = "Value.")] public string Value { get; set; } + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } + [Usage(ApplicationAlias = "mono testapp.exe")] public static IEnumerable Examples { @@ -78,6 +94,16 @@ public static IEnumerable Examples } } + [Verb("secert", Hidden = true, HelpText = "This is a secert hidden verb that should never be visible to the user via help text.")] + public class Secert_Verb + { + [Option('f', "force", SetName = "mode-f", HelpText = "Allow adding otherwise ignored files.")] + public bool Force { get; set; } + + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } + } + [Verb("add", HelpText = "Add file contents to the index.")] public class Add_Verb_With_Usage_Attribute { @@ -92,6 +118,9 @@ public class Add_Verb_With_Usage_Attribute [Value(0)] public string FileName { get; set; } + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } + [Usage(ApplicationAlias = "git")] public static IEnumerable Examples { @@ -112,6 +141,9 @@ public class Commit_Verb_With_Usage_Attribute [Option("amend", HelpText = "Used to amend the tip of the current branch.")] public bool Amend { get; set; } + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } + [Usage(ApplicationAlias = "git")] public static IEnumerable Examples { @@ -133,6 +165,9 @@ public class Clone_Verb_With_Usage_Attribute HelpText = "Suppress summary message.")] public bool Quiet { get; set; } + [Option("secert-option", Hidden = true, HelpText = "This is a description for a secert hidden option that should never be visibile to the user via help text.")] + public string SecertOption { get; set; } + [Value(0, MetaName = "URLS", HelpText = "A list of url(s) to clone.")] public IEnumerable Urls { get; set; } diff --git a/tests/CommandLine.Tests/Unit/ParserTests.cs b/tests/CommandLine.Tests/Unit/ParserTests.cs index 0989f32c..f058aa05 100644 --- a/tests/CommandLine.Tests/Unit/ParserTests.cs +++ b/tests/CommandLine.Tests/Unit/ParserTests.cs @@ -492,6 +492,91 @@ public void Properly_formatted_help_screen_is_displayed_when_usage_is_defined_in // Teardown } + [Fact] + public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_verb() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => config.HelpWriter = help); + + // Exercize system + sut.ParseArguments(new string[] { }); + var result = help.ToString(); + + // Verify outcome + var lines = result.ToNotEmptyLines().TrimStringArray(); + lines[0].Should().StartWithEquivalent("CommandLine"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[2].ShouldBeEquivalentTo("ERROR(S):"); + lines[3].ShouldBeEquivalentTo("No verb selected."); + lines[4].ShouldBeEquivalentTo("add Add file contents to the index."); + lines[5].ShouldBeEquivalentTo("help Display more information on a specific command."); + lines[6].ShouldBeEquivalentTo("version Display version information."); + + // Teardown + } + + [Fact] + public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_verb_selected_usage_displays_with_hidden_option() + { + // Fixture setup + var help = new StringWriter(); + var sut = new Parser(config => config.HelpWriter = help); + + // Exercize system + sut.ParseArguments(new string[] { "secert", "--help" }); + var result = help.ToString(); + + // Verify outcome + var lines = result.ToNotEmptyLines().TrimStringArray(); + lines[0].Should().StartWithEquivalent("CommandLine"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); + lines[2].ShouldBeEquivalentTo("-f, --force Allow adding otherwise ignored files."); + lines[3].ShouldBeEquivalentTo("--help Display this help screen."); + lines[4].ShouldBeEquivalentTo("--version Display version information."); + + // Teardown + } + + [Fact] + public void Parse_options_when_given_hidden_verb() + { + // Fixture setup + var expectedOptions = new Secert_Verb { Force = true, SecertOption = null}; + var help = new StringWriter(); + var sut = new Parser(config => config.HelpWriter = help); + + // Exercize system + var result = sut.ParseArguments(new string[] { "secert", "--force" }); + + + // Verify outcome + result.Tag.ShouldBeEquivalentTo(ParserResultType.Parsed); + result.GetType().Should().Be>(); + result.TypeInfo.Current.Should().Be(); + ((Parsed)result).Value.ShouldBeEquivalentTo(expectedOptions, o => o.RespectingRuntimeTypes()); + // Teardown + } + + [Fact] + public void Parse_options_when_given_hidden_verb_with_hidden_option() + { + // Fixture setup + var expectedOptions = new Secert_Verb { Force = true, SecertOption = "shhh" }; + var help = new StringWriter(); + var sut = new Parser(config => config.HelpWriter = help); + + // Exercize system + var result = sut.ParseArguments(new string[] { "secert", "--force", "--secert-option", "shhh" }); + + // Verify outcome + result.Tag.ShouldBeEquivalentTo(ParserResultType.Parsed); + result.GetType().Should().Be>(); + result.TypeInfo.Current.Should().Be(); + ((Parsed)result).Value.ShouldBeEquivalentTo(expectedOptions, o => o.RespectingRuntimeTypes()); + // Teardown + } + [Fact] public void Specific_verb_help_screen_should_be_displayed_regardless_other_argument() { diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 4c5defe0..f0403982 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -152,7 +152,7 @@ public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_c lines[6].ShouldBeEquivalentTo(" Help Text."); // Teardown } - + [Fact] @@ -161,7 +161,6 @@ public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_c // Fixture setup // Exercize system var sut = new HelpText(new HeadingInfo("CommandLine.Tests.dll", "1.9.4.131")) { MaximumDisplayWidth = 100} ; - //sut.MaximumDisplayWidth = 100; sut.AddOptions( new NotParsed( TypeInfo.Create(typeof(Simple_Options_With_HelpText_Set_To_Long_Description)), @@ -175,6 +174,25 @@ public void When_help_text_is_longer_than_width_it_will_wrap_around_as_if_in_a_c // Teardown } + [Fact] + public void When_help_text_has_hidden_option_it_should_not_be_added_to_help_text_output() + { + // Fixture setup + // Exercize system + var sut = new HelpText(new HeadingInfo("CommandLine.Tests.dll", "1.9.4.131")); + sut.AddOptions( + new NotParsed( + TypeInfo.Create(typeof(Simple_Options_With_HelpText_Set_To_Long_Description)), + Enumerable.Empty())); + + // Verify outcome + var lines = sut.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + lines[2].ShouldBeEquivalentTo(" v, verbose This is the description of the verbosity to test out the "); //"The first line should have the arguments and the start of the Help Text."); + //string formattingMessage = "Beyond the second line should be formatted as though it's in a column."; + lines[3].ShouldBeEquivalentTo(" wrapping capabilities of the Help Text."); + // Teardown + } + [Fact] public void Long_help_text_without_spaces() { @@ -458,7 +476,7 @@ public void Invoke_AutoBuild_for_Options_with_Usage_returns_appropriate_formatte var helpText = HelpText.AutoBuild(fakeResult); // Verify outcome - var text = helpText.ToString(); + var text = helpText.ToString(); var lines = text.ToNotEmptyLines().TrimStringArray(); lines[0].Should().StartWithEquivalent("CommandLine"); lines[1].Should().StartWithEquivalent("Copyright (c)"); From 2912a6f399ebe3ad3da77ece24902d0e1f3890ee Mon Sep 17 00:00:00 2001 From: Bill Boga Date: Wed, 20 Jul 2016 12:03:49 -0400 Subject: [PATCH 04/26] Allow spaces when tokenizing option-value Previous behavior split the incoming token long-name value using the equal sign as the separator. This would cause an option's value containing spaces to get truncated. New behavior does regex. match to make sure format is correct and gets the full value. --- src/CommandLine/Core/Tokenizer.cs | 17 +++++++-- .../Unit/Core/TokenizerTests.cs | 35 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/CommandLine/Core/Tokenizer.cs b/src/CommandLine/Core/Tokenizer.cs index 902b65e4..e0e09fd3 100644 --- a/src/CommandLine/Core/Tokenizer.cs +++ b/src/CommandLine/Core/Tokenizer.cs @@ -6,6 +6,7 @@ using CommandLine.Infrastructure; using CSharpx; using RailwaySharp.ErrorHandling; +using System.Text.RegularExpressions; namespace CommandLine.Core { @@ -188,9 +189,19 @@ private static IEnumerable TokenizeLongName( onError(new BadFormatTokenError(value)); yield break; } - var parts = text.Split('='); - yield return Token.Name(parts[0]); - yield return Token.Value(parts[1], true); + + var tokenMatch = Regex.Match(text, "^([^=]+)=([^ ].*)$"); + + if (tokenMatch.Success) + { + yield return Token.Name(tokenMatch.Groups[1].Value); + yield return Token.Value(tokenMatch.Groups[2].Value, true); + } + else + { + onError(new BadFormatTokenError(value)); + yield break; + } } } } diff --git a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs index 37dbe51f..bceb1ea0 100644 --- a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs @@ -92,6 +92,41 @@ public void Normalize_should_remove_all_value_with_explicit_assignment_of_existi // Teardown } + + [Fact] + public void Should_properly_parse_option_with_equals_in_value() + { + /** + * This is how the arg. would look in `static void Main(string[] args)` + * if passed from the command-line and the option-value wrapped in quotes. + * Ex.) ./app --connectionString="Server=localhost;Data Source..." + */ + var args = new[] { "--connectionString=Server=localhost;Data Source=(LocalDB)\v12.0;Initial Catalog=temp;" }; + + var result = Tokenizer.Tokenize(args, name => NameLookupResult.OtherOptionFound, token => token); + + var tokens = result.SucceededWith(); + + Assert.NotNull(tokens); + Assert.Equal(2, tokens.Count()); + Assert.Equal("connectionString", tokens.First().Text); + Assert.Equal("Server=localhost;Data Source=(LocalDB)\v12.0;Initial Catalog=temp;", tokens.Last().Text); + } + + [Fact] + public void Should_return_error_if_option_format_with_equals_is_not_correct() + { + var args = new[] { "--option1 = fail", "--option2= fail" }; + + var result = Tokenizer.Tokenize(args, name => NameLookupResult.OtherOptionFound, token => token); + + var tokens = result.SuccessfulMessages(); + + Assert.NotNull(tokens); + Assert.Equal(2, tokens.Count()); + Assert.Equal(ErrorType.BadFormatTokenError, tokens.First().Tag); + Assert.Equal(ErrorType.BadFormatTokenError, tokens.Last().Tag); + } } } From d2965891db45caddb2f6346f0faae8e6f0a8c43c Mon Sep 17 00:00:00 2001 From: Alexander Fast Date: Sat, 6 Aug 2016 13:52:38 +0200 Subject: [PATCH 05/26] Update README.md Fixed typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6387fa5b..ef71df61 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ static int Main(string[] args) { var result = CommandLine.Parser.Default.ParseArguments(args); var exitCode = result .MapResult( - options = > { + options => { if (options.Verbose) Console.WriteLine("Filenames: {0}", string.Join(",", options.InputFiles.ToArray())); return 0; }, errors => { From ecb9e643ed99e7ff49e8e5111980cead2e66284d Mon Sep 17 00:00:00 2001 From: Dan Nemec Date: Sun, 7 Aug 2016 02:41:07 -0500 Subject: [PATCH 06/26] Fix unit tests for new code merged before Core migration --- src/CommandLine/project.json | 5 +++-- tests/CommandLine.Tests/Fakes/Help_Fakes.cs | 1 - tests/CommandLine.Tests/Unit/ParserTests.cs | 12 ++++++++++++ tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs | 10 ++++++++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/CommandLine/project.json b/src/CommandLine/project.json index 11eafe2e..a8a53bcc 100644 --- a/src/CommandLine/project.json +++ b/src/CommandLine/project.json @@ -41,7 +41,8 @@ "System.Linq": "4.1.0", "System.Diagnostics.Debug": "4.0.11", "System.Console": "4.0.0", - "System.Reflection.Extensions": "4.0.1" + "System.Reflection.Extensions": "4.0.1", + "System.Text.RegularExpressions": "4.1.0" }, "imports": [ "netcore45" ] }, @@ -55,4 +56,4 @@ "frameworkAssemblies": { } } } -} \ No newline at end of file +} diff --git a/tests/CommandLine.Tests/Fakes/Help_Fakes.cs b/tests/CommandLine.Tests/Fakes/Help_Fakes.cs index a35e8599..cceb5331 100644 --- a/tests/CommandLine.Tests/Fakes/Help_Fakes.cs +++ b/tests/CommandLine.Tests/Fakes/Help_Fakes.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using CommandLine.Text; -using Microsoft.FSharp.Collections; namespace CommandLine.Tests.Fakes { diff --git a/tests/CommandLine.Tests/Unit/ParserTests.cs b/tests/CommandLine.Tests/Unit/ParserTests.cs index 21e2b533..5e15d61b 100644 --- a/tests/CommandLine.Tests/Unit/ParserTests.cs +++ b/tests/CommandLine.Tests/Unit/ParserTests.cs @@ -539,8 +539,14 @@ public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_v // Verify outcome var lines = result.ToNotEmptyLines().TrimStringArray(); +#if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); +#else + // Takes the name of the xUnit test program + lines[0].Should().StartWithEquivalent("xUnit"); + lines[1].Should().StartWithEquivalent("Copyright (C) Outercurve Foundation"); +#endif lines[2].ShouldBeEquivalentTo("ERROR(S):"); lines[3].ShouldBeEquivalentTo("No verb selected."); lines[4].ShouldBeEquivalentTo("add Add file contents to the index."); @@ -563,8 +569,14 @@ public void Properly_formatted_help_screen_is_displayed_when_there_is_a_hidden_v // Verify outcome var lines = result.ToNotEmptyLines().TrimStringArray(); +#if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); +#else + // Takes the name of the xUnit test program + lines[0].Should().StartWithEquivalent("xUnit"); + lines[1].Should().StartWithEquivalent("Copyright (C) Outercurve Foundation"); +#endif lines[2].ShouldBeEquivalentTo("-f, --force Allow adding otherwise ignored files."); lines[3].ShouldBeEquivalentTo("--help Display this help screen."); lines[4].ShouldBeEquivalentTo("--version Display version information."); diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 17863abd..f33fff36 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -384,8 +384,14 @@ public void Invoke_AutoBuild_for_Verbs_with_specific_verb_returns_appropriate_fo // Verify outcome var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray(); +#if !PLATFORM_DOTNET lines[0].Should().StartWithEquivalent("CommandLine"); - lines[1].Should().StartWithEquivalent("Copyright (c)"); + lines[1].ShouldBeEquivalentTo("Copyright (c) 2005 - 2015 Giacomo Stelluti Scala"); +#else + // Takes the name of the xUnit test program + lines[0].Should().StartWithEquivalent("xUnit"); + lines[1].Should().StartWithEquivalent("Copyright (C) Outercurve Foundation"); +#endif lines[2].ShouldBeEquivalentTo("-p, --patch Use the interactive patch selection interface to chose which changes to commit."); lines[3].ShouldBeEquivalentTo("--amend Used to amend the tip of the current branch."); lines[4].ShouldBeEquivalentTo("-m, --message Use the given message as the commit message."); @@ -559,4 +565,4 @@ public void Default_set_to_sequence_should_be_properly_printed() } #endif } -} \ No newline at end of file +} From 9ff3c90990218392358c21e536cb0f918f63edb1 Mon Sep 17 00:00:00 2001 From: Dan Nemec Date: Sun, 7 Aug 2016 02:57:24 -0500 Subject: [PATCH 07/26] Start VB.NET examples in README --- README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/README.md b/README.md index ef71df61..865cbac7 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,32 @@ let main argv = | :? Parsed as parsed -> run parsed.Value | :? NotParsed as notParsed -> fail notParsed.Errors ``` +**VB.NET:** +```VB.NET +Class Options + + Public Property InputFiles As IEnumerable(Of String) + + ' Omitting long name, default --verbose + + Public Property Verbose As Boolean + + + Public Property Language As String + + + Public Property Offset As Long? +End Class +``` +Consume them: +```VB.NET +TODO +``` + For verbs: @@ -176,6 +202,25 @@ let main args = | :? CloneOptions as opts -> RunCloneAndReturnExitCode opts | :? CommandLine.NotParsed -> 1 ``` +**VB.NET:** +```VB.NET + +Public Class AddOptions + 'Normal options here +End Class + +Public Class AddOptions + 'Normal options here +End Class + +Public Class AddOptions + 'Normal options here +End Class + +Public Shared Sub Main() + 'TODO +End Sub +``` Acknowledgements: --- From 4e15d55acf50da9e503e903c7d100b9c0daa2ee7 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 00:05:22 +1000 Subject: [PATCH 08/26] Get building. Newer tools require some config changes. xUnit also has incompatibilities with .Net 4.0 assemblies. --- .gitignore | 4 +- .../CommandLine.Tests.csproj | 38 ++++--------------- tests/CommandLine.Tests/project.json | 33 ++++------------ 3 files changed, 17 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index a7d34775..7f2e43bd 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,6 @@ artifacts/* .vs/* *.xproj.user *.nuget.targets -*.lock.json \ No newline at end of file +*.lock.json +*.nuget.props + diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index f3c6925b..ca3b7233 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -124,15 +124,15 @@ Designer + + + - {E1BD3C65-49C3-49E7-BABA-C60980CB3F20} + {e1bd3c65-49c3-49e7-baba-c60980cb3f20} CommandLine - - - @@ -389,15 +389,7 @@ - - - - ..\..\packages\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - + @@ -409,26 +401,10 @@ - - - - ..\..\packages\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - True - - - + - - - - ..\..\packages\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - True - True - - - + diff --git a/tests/CommandLine.Tests/project.json b/tests/CommandLine.Tests/project.json index 424a45a0..8d96e778 100644 --- a/tests/CommandLine.Tests/project.json +++ b/tests/CommandLine.Tests/project.json @@ -1,33 +1,14 @@ -{ +{ "version": "1.0.0-*", "description": "CommandLine.DotNet.Tests", - "dependencies": { - "xunit": "2.1.0", - "CommandLine": { - "target": "project" - } + "xunit": "2.1.0" }, - "testRunner": "xunit", - + "runtimes": { + "win": {} + }, "frameworks": { - "netcoreapp1.0": { - "buildOptions": { - "define": [ "PLATFORM_DOTNET", "SKIP_FSHARP" ], - "keyFile": "../../CommandLine.snk" - }, - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - }, - "System.Reflection": "4.1.0", - "System.Reflection.TypeExtensions": "4.1.0", - "FluentAssertions": "4.2.2", - "dotnet-test-xunit": "2.2.0-*" - }, - "imports": [ "dotnet5.4", "dnxcore50", "portable-net451+win81" ] - } + ".NETFramework,Version=v4.5": {} } -} +} \ No newline at end of file From 9dd1adb4d539387e162a905f105eb199c27ab0cc Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 00:14:47 +1000 Subject: [PATCH 09/26] Add missing XML comments --- src/CommandLine/Error.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/CommandLine/Error.cs b/src/CommandLine/Error.cs index 9739a18a..475ac8e3 100644 --- a/src/CommandLine/Error.cs +++ b/src/CommandLine/Error.cs @@ -157,6 +157,11 @@ public abstract class TokenError : Error, IEquatable { private readonly string token; + /// + /// Initializes a new instance of the class. + /// + /// Error type. + /// Problematic token. protected internal TokenError(ErrorType tag, string token) : base(tag) { @@ -232,6 +237,12 @@ public abstract class NamedError : Error, IEquatable { private readonly NameInfo nameInfo; + /// + /// Initializes a new instance of the class. + /// + /// Error type. + /// Problematic name. + protected internal NamedError(ErrorType tag, NameInfo nameInfo) : base(tag) { From a7fd065ae13563001a9bc1d60343ed51e804115f Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 00:39:29 +1000 Subject: [PATCH 10/26] Initial implementation --- src/CommandLine/Text/CopyrightInfo.cs | 12 ++++++++++++ src/CommandLine/Text/HeadingInfo.cs | 11 +++++++++++ src/CommandLine/Text/HelpText.cs | 14 ++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/CommandLine/Text/CopyrightInfo.cs b/src/CommandLine/Text/CopyrightInfo.cs index 8db2a532..3df9e630 100644 --- a/src/CommandLine/Text/CopyrightInfo.cs +++ b/src/CommandLine/Text/CopyrightInfo.cs @@ -1,6 +1,7 @@ // Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. using System; +using System.Dynamic; using System.Globalization; using System.Reflection; using System.Text; @@ -24,6 +25,17 @@ public class CopyrightInfo private readonly string author; private readonly int builderSize; + /// + /// An empty object used for initialization. + /// + public static CopyrightInfo Empty + { + get + { + return new CopyrightInfo("author", 1); + } + } + /// /// Initializes a new instance of the class /// specifying author and year. diff --git a/src/CommandLine/Text/HeadingInfo.cs b/src/CommandLine/Text/HeadingInfo.cs index dfe95edd..286a1872 100644 --- a/src/CommandLine/Text/HeadingInfo.cs +++ b/src/CommandLine/Text/HeadingInfo.cs @@ -33,6 +33,17 @@ public HeadingInfo(string programName, string version = null) this.version = version; } + /// + /// An empty object used for initialization. + /// + public static HeadingInfo Empty + { + get + { + return new HeadingInfo(""); + } + } + /// /// Gets the default heading instance. /// The title is retrieved from , diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 9209e25c..68f7af3b 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -212,13 +212,23 @@ public static HelpText AutoBuild( { var auto = new HelpText { - Heading = HeadingInfo.Default, - Copyright = CopyrightInfo.Default, + Heading = HeadingInfo.Empty, + Copyright = CopyrightInfo.Empty, AdditionalNewLineAfterOption = true, AddDashesToOption = !verbsIndex, MaximumDisplayWidth = maxDisplayWidth }; + try + { + auto.Heading = HeadingInfo.Default; + auto.Copyright = CopyrightInfo.Default; + } + catch (Exception) + { + auto = onError(auto); + } + var errors = Enumerable.Empty(); if (onError != null && parserResult.Tag == ParserResultType.NotParsed) From 8b0c55cd9e6b970416569677a0b246874e80db99 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 12:05:23 +1000 Subject: [PATCH 11/26] Starting tests --- .../Infrastructure/ReflectionHelper.cs | 19 +++++++++++++++++++ .../Unit/Text/HelpTextTests.cs | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index 97aac26f..0ada4f1d 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -1,6 +1,7 @@ // 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.Generic; using System.Linq; using System.Reflection; using CommandLine.Core; @@ -10,9 +11,27 @@ namespace CommandLine.Infrastructure { static class ReflectionHelper { + private static IDictionary _overrides; + + public static void SetAttributeOverride(IDictionary overrides) + { + if (overrides == null) + { + throw new ArgumentNullException(nameof(overrides)); + } + + _overrides = overrides; + } + public static Maybe GetAttribute() where TAttribute : Attribute { + // Test support + if (_overrides != null && _overrides.ContainsKey(typeof (TAttribute))) + { + return Maybe.Just((TAttribute) _overrides[typeof (TAttribute)]); + } + var assembly = GetExecutingOrEntryAssembly(); #if NET40 diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index f33fff36..35c647ce 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -564,5 +564,18 @@ public void Default_set_to_sequence_should_be_properly_printed() // Teardown } #endif + + [Fact] + public void AutoBuild_when_no_assembly_attributes() + { + ParserResult fakeResult = new NotParsed( + TypeInfo.Create(typeof(Simple_Options)), + new Error[] + { + new BadFormatTokenError("badtoken"), + new SequenceOutOfRangeError(new NameInfo("i", "")) + }); + HelpText helpText = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + } } } From 31adc9e1edde016af312e447634170da5a17b2fb Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 18:17:14 +1000 Subject: [PATCH 12/26] Working on tests --- .../Infrastructure/ReflectionHelper.cs | 12 ++++------ src/CommandLine/Text/HelpText.cs | 18 ++++++++++++++- .../Unit/Text/HelpTextTests.cs | 23 ++++++++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index 0ada4f1d..ec90f2c4 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -15,11 +15,6 @@ static class ReflectionHelper public static void SetAttributeOverride(IDictionary overrides) { - if (overrides == null) - { - throw new ArgumentNullException(nameof(overrides)); - } - _overrides = overrides; } @@ -27,9 +22,12 @@ public static Maybe GetAttribute() where TAttribute : Attribute { // Test support - if (_overrides != null && _overrides.ContainsKey(typeof (TAttribute))) + if (_overrides != null) { - return Maybe.Just((TAttribute) _overrides[typeof (TAttribute)]); + return + _overrides.ContainsKey(typeof(TAttribute)) ? + Maybe.Just((TAttribute)_overrides[typeof(TAttribute)]) : + Maybe.Nothing< TAttribute>(); } var assembly = GetExecutingOrEntryAssembly(); diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 68f7af3b..418faa1a 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -17,7 +17,7 @@ namespace CommandLine.Text /// Provides means to format an help screen. /// You can assign it in place of a instance. /// - public class HelpText + public class HelpText: IEquatable { private const int BuilderCapacity = 128; private const int DefaultMaximumLength = 80; // default console width @@ -597,6 +597,22 @@ public static IEnumerable RenderUsageTextAsLines(ParserResult pars } } + /// + /// + /// + /// + /// + public bool Equals(HelpText other) + { + return other != null + && other.AddDashesToOption == AddDashesToOption + && other.AddEnumValuesToHelpText == AddEnumValuesToHelpText + && other.AdditionalNewLineAfterOption == AdditionalNewLineAfterOption + && other.Copyright.Equals(Copyright) + && other.Heading.Equals(Heading) + && other.MaximumDisplayWidth == MaximumDisplayWidth; + } + /// /// Returns the help screen as a . /// diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 35c647ce..672de61a 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -5,7 +5,9 @@ using System.Globalization; using System.Linq; using CommandLine.Core; +using CommandLine.Infrastructure; using CommandLine.Tests.Fakes; +using CommandLine.Tests.Unit.Infrastructure; using CommandLine.Text; using FluentAssertions; using Xunit; @@ -568,14 +570,23 @@ public void Default_set_to_sequence_should_be_properly_printed() [Fact] public void AutoBuild_when_no_assembly_attributes() { - ParserResult fakeResult = new NotParsed( - TypeInfo.Create(typeof(Simple_Options)), - new Error[] - { + try + { + ReflectionHelper.SetAttributeOverride(new Dictionary()); + + ParserResult fakeResult = new NotParsed( + TypeInfo.Create(typeof(Simple_Options)), + new Error[] + { new BadFormatTokenError("badtoken"), new SequenceOutOfRangeError(new NameInfo("i", "")) - }); - HelpText helpText = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + }); + HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + } + finally + { + ReflectionHelper.SetAttributeOverride(null); + } } } } From 211f073e959e5bf1b5fcc82b2306a90280192aae Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 22:11:08 +1000 Subject: [PATCH 13/26] Finish first draft of unit tests --- .../Unit/Text/HelpTextTests.cs | 74 +++++++++++++++++-- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 672de61a..936e2598 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Reflection; using CommandLine.Core; using CommandLine.Infrastructure; using CommandLine.Tests.Fakes; @@ -572,16 +573,75 @@ public void AutoBuild_when_no_assembly_attributes() { try { + string expectedCopyright = "Copyright (C) 1 author"; + ReflectionHelper.SetAttributeOverride(new Dictionary()); ParserResult fakeResult = new NotParsed( - TypeInfo.Create(typeof(Simple_Options)), - new Error[] - { - new BadFormatTokenError("badtoken"), - new SequenceOutOfRangeError(new NameInfo("i", "")) - }); - HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + TypeInfo.Create(typeof (Simple_Options)), new Error[0]); + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + + actualResult.Copyright.Should().Be(expectedCopyright); + } + finally + { + ReflectionHelper.SetAttributeOverride(null); + } + } + + [Fact] + public void AutoBuild_with_assembly_title_and_version_attributes_only() + { + try + { + string expectedTitle = "Title"; + string expectedVersion = "1.2.3.4"; + + ReflectionHelper.SetAttributeOverride(new Dictionary + { + { + typeof(AssemblyTitleAttribute), + new AssemblyTitleAttribute(expectedTitle) + }, + { + typeof(AssemblyInformationalVersionAttribute), + new AssemblyInformationalVersionAttribute(expectedVersion) + } + }); + + ParserResult fakeResult = new NotParsed( + TypeInfo.Create(typeof (Simple_Options)), new Error[0]); + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + + actualResult.Heading.Should().Be(string.Format("{0} {1}", expectedTitle, expectedVersion)); + } + finally + { + ReflectionHelper.SetAttributeOverride(null); + } + } + + + [Fact] + public void AutoBuild_with_assembly_company_attribute_only() + { + try + { + string expectedCompany = "Company"; + + ReflectionHelper.SetAttributeOverride(new Dictionary + { + { + typeof(AssemblyCompanyAttribute), + new AssemblyCompanyAttribute(expectedCompany) + } + }); + + ParserResult fakeResult = new NotParsed( + TypeInfo.Create(typeof (Simple_Options)), new Error[0]); + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + + actualResult.Copyright.Should().Be(string.Format("Copyright (C) {0} {1}", DateTime.Now.Year, expectedCompany)); } finally { From 7b82ada8f3407553bfaf1e56226de7abda9b3da5 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 22:19:10 +1000 Subject: [PATCH 14/26] Made new tests thread safe --- .../Infrastructure/ReflectionHelper.cs | 28 +++++++++++++++++-- .../Unit/Text/HelpTextTests.cs | 21 ++++---------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index ec90f2c4..aa5ea65b 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.Remoting.Messaging; using CommandLine.Core; using CSharpx; @@ -11,11 +12,32 @@ namespace CommandLine.Infrastructure { static class ReflectionHelper { - private static IDictionary _overrides; + /// + /// Per thread assembly attribute overrides for testing. + /// + [ThreadStatic] private static IDictionary _overrides; - public static void SetAttributeOverride(IDictionary overrides) + /// + /// Assembly attribute overrides for testing. + /// + /// + /// The implementation will fail if two or more attributes of the same type + /// are included in . + /// + /// + /// Attributes that replace the existing assembly attributes or null, + /// to clear any testing attributes. + /// + public static void SetAttributeOverride(IList overrides) { - _overrides = overrides; + if (overrides != null) + { + _overrides = overrides.ToDictionary(attr => attr.GetType(), attr => attr); + } + else + { + _overrides = null; + } } public static Maybe GetAttribute() diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index 936e2598..d901b17c 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -575,7 +575,7 @@ public void AutoBuild_when_no_assembly_attributes() { string expectedCopyright = "Copyright (C) 1 author"; - ReflectionHelper.SetAttributeOverride(new Dictionary()); + ReflectionHelper.SetAttributeOverride(new Attribute[0]); ParserResult fakeResult = new NotParsed( TypeInfo.Create(typeof (Simple_Options)), new Error[0]); @@ -597,16 +597,10 @@ public void AutoBuild_with_assembly_title_and_version_attributes_only() string expectedTitle = "Title"; string expectedVersion = "1.2.3.4"; - ReflectionHelper.SetAttributeOverride(new Dictionary + ReflectionHelper.SetAttributeOverride(new Attribute[] { - { - typeof(AssemblyTitleAttribute), - new AssemblyTitleAttribute(expectedTitle) - }, - { - typeof(AssemblyInformationalVersionAttribute), - new AssemblyInformationalVersionAttribute(expectedVersion) - } + new AssemblyTitleAttribute(expectedTitle), + new AssemblyInformationalVersionAttribute(expectedVersion) }); ParserResult fakeResult = new NotParsed( @@ -629,12 +623,9 @@ public void AutoBuild_with_assembly_company_attribute_only() { string expectedCompany = "Company"; - ReflectionHelper.SetAttributeOverride(new Dictionary + ReflectionHelper.SetAttributeOverride(new Attribute[] { - { - typeof(AssemblyCompanyAttribute), - new AssemblyCompanyAttribute(expectedCompany) - } + new AssemblyCompanyAttribute(expectedCompany) }); ParserResult fakeResult = new NotParsed( From 55a3f3594d7b5be9ac38d46bf356a0e133e14afd Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 22:21:37 +1000 Subject: [PATCH 15/26] Remove unneeded IEquatable --- src/CommandLine/Text/HelpText.cs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/CommandLine/Text/HelpText.cs b/src/CommandLine/Text/HelpText.cs index 418faa1a..68f7af3b 100644 --- a/src/CommandLine/Text/HelpText.cs +++ b/src/CommandLine/Text/HelpText.cs @@ -17,7 +17,7 @@ namespace CommandLine.Text /// Provides means to format an help screen. /// You can assign it in place of a instance. /// - public class HelpText: IEquatable + public class HelpText { private const int BuilderCapacity = 128; private const int DefaultMaximumLength = 80; // default console width @@ -597,22 +597,6 @@ public static IEnumerable RenderUsageTextAsLines(ParserResult pars } } - /// - /// - /// - /// - /// - public bool Equals(HelpText other) - { - return other != null - && other.AddDashesToOption == AddDashesToOption - && other.AddEnumValuesToHelpText == AddEnumValuesToHelpText - && other.AdditionalNewLineAfterOption == AdditionalNewLineAfterOption - && other.Copyright.Equals(Copyright) - && other.Heading.Equals(Heading) - && other.MaximumDisplayWidth == MaximumDisplayWidth; - } - /// /// Returns the help screen as a . /// From d10f3678fd9760c0b0a41299ce519de2c9fd6cd6 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sat, 1 Oct 2016 22:33:16 +1000 Subject: [PATCH 16/26] Check on error called. Also changed IList to IEnumerable. --- .../Infrastructure/ReflectionHelper.cs | 4 ++-- .../Unit/Text/HelpTextTests.cs | 24 ++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index aa5ea65b..bec7d470 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -28,7 +28,7 @@ static class ReflectionHelper /// Attributes that replace the existing assembly attributes or null, /// to clear any testing attributes. /// - public static void SetAttributeOverride(IList overrides) + public static void SetAttributeOverride(IEnumerable overrides) { if (overrides != null) { @@ -46,7 +46,7 @@ public static Maybe GetAttribute() // Test support if (_overrides != null) { - return + return _overrides.ContainsKey(typeof(TAttribute)) ? Maybe.Just((TAttribute)_overrides[typeof(TAttribute)]) : Maybe.Nothing< TAttribute>(); diff --git a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs index d901b17c..6d7e8099 100644 --- a/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs +++ b/tests/CommandLine.Tests/Unit/Text/HelpTextTests.cs @@ -579,8 +579,14 @@ public void AutoBuild_when_no_assembly_attributes() ParserResult fakeResult = new NotParsed( TypeInfo.Create(typeof (Simple_Options)), new Error[0]); - HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + bool onErrorCalled = false; + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => + { + onErrorCalled = true; + return ht; + }, ex => ex); + onErrorCalled.Should().BeTrue(); actualResult.Copyright.Should().Be(expectedCopyright); } finally @@ -605,8 +611,14 @@ public void AutoBuild_with_assembly_title_and_version_attributes_only() ParserResult fakeResult = new NotParsed( TypeInfo.Create(typeof (Simple_Options)), new Error[0]); - HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + bool onErrorCalled = false; + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => + { + onErrorCalled = true; + return ht; + }, ex => ex); + onErrorCalled.Should().BeTrue(); actualResult.Heading.Should().Be(string.Format("{0} {1}", expectedTitle, expectedVersion)); } finally @@ -630,8 +642,14 @@ public void AutoBuild_with_assembly_company_attribute_only() ParserResult fakeResult = new NotParsed( TypeInfo.Create(typeof (Simple_Options)), new Error[0]); - HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => ht, ex => ex); + bool onErrorCalled = false; + HelpText actualResult = HelpText.AutoBuild(fakeResult, ht => + { + onErrorCalled = true; + return ht; + }, ex => ex); + onErrorCalled.Should().BeFalse(); // Other attributes have fallback logic actualResult.Copyright.Should().Be(string.Format("Copyright (C) {0} {1}", DateTime.Now.Year, expectedCompany)); } finally From 13d8b581adf34e31b40d99386e878dd3e0f4b6f1 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Sun, 2 Oct 2016 11:59:56 +1100 Subject: [PATCH 17/26] Revert csproj and project.json for CI --- .../CommandLine.Tests.csproj | 38 +++++++++++++++---- tests/CommandLine.Tests/project.json | 33 ++++++++++++---- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index ca3b7233..f3c6925b 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -124,15 +124,15 @@ Designer - - - - {e1bd3c65-49c3-49e7-baba-c60980cb3f20} + {E1BD3C65-49C3-49E7-BABA-C60980CB3F20} CommandLine + + + @@ -389,7 +389,15 @@ - + + + + ..\..\packages\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + @@ -401,10 +409,26 @@ - + + + + ..\..\packages\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + - + + + + ..\..\packages\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + diff --git a/tests/CommandLine.Tests/project.json b/tests/CommandLine.Tests/project.json index 8d96e778..424a45a0 100644 --- a/tests/CommandLine.Tests/project.json +++ b/tests/CommandLine.Tests/project.json @@ -1,14 +1,33 @@ -{ +{ "version": "1.0.0-*", "description": "CommandLine.DotNet.Tests", + "dependencies": { - "xunit": "2.1.0" + "xunit": "2.1.0", + "CommandLine": { + "target": "project" + } }, + "testRunner": "xunit", - "runtimes": { - "win": {} - }, + "frameworks": { - ".NETFramework,Version=v4.5": {} + "netcoreapp1.0": { + "buildOptions": { + "define": [ "PLATFORM_DOTNET", "SKIP_FSHARP" ], + "keyFile": "../../CommandLine.snk" + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + }, + "System.Reflection": "4.1.0", + "System.Reflection.TypeExtensions": "4.1.0", + "FluentAssertions": "4.2.2", + "dotnet-test-xunit": "2.2.0-*" + }, + "imports": [ "dotnet5.4", "dnxcore50", "portable-net451+win81" ] + } } -} \ No newline at end of file +} From 47d717e98302a272871c517fe41b4938b45dd158 Mon Sep 17 00:00:00 2001 From: Yong Heng Date: Tue, 4 Oct 2016 21:56:02 +0800 Subject: [PATCH 18/26] Update README.md fix outdated README section under csharp with working example. --- README.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 865cbac7..f42bb4e9 100644 --- a/README.md +++ b/README.md @@ -91,17 +91,8 @@ class Options { Consume them: ```csharp static int Main(string[] args) { - var result = CommandLine.Parser.Default.ParseArguments(args); - var exitCode = result - .MapResult( - options => { - if (options.Verbose) Console.WriteLine("Filenames: {0}", string.Join(",", options.InputFiles.ToArray())); - return 0; }, - errors => { - LogHelper.Log(errors); - return 1; }); - return exitCode; -} + var options = new Options(); + var isValid = CommandLine.Parser.Default.ParseArgumentsStrict(args, options); ``` **F#:** ```fsharp From d4e0b25ecf19ebb0b4212cae21f7b9c832e54fb9 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 21:46:22 +1100 Subject: [PATCH 19/26] Revert "Get building." This reverts commit 4e15d55acf50da9e503e903c7d100b9c0daa2ee7. --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7f2e43bd..a7d34775 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,4 @@ artifacts/* .vs/* *.xproj.user *.nuget.targets -*.lock.json -*.nuget.props - +*.lock.json \ No newline at end of file From 4669688b5453bcffece4654c4413a98d9e8d1875 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 21:47:34 +1100 Subject: [PATCH 20/26] Revert "Revert "Get building."" This reverts commit d4e0b25ecf19ebb0b4212cae21f7b9c832e54fb9. --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a7d34775..7f2e43bd 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,6 @@ artifacts/* .vs/* *.xproj.user *.nuget.targets -*.lock.json \ No newline at end of file +*.lock.json +*.nuget.props + From a6223763cdfe117289d0854ef6e13833c2367e55 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 21:56:51 +1100 Subject: [PATCH 21/26] Get building locally --- .../CommandLine.Tests.csproj | 38 ++++--------------- tests/CommandLine.Tests/project.json | 33 ++++------------ 2 files changed, 14 insertions(+), 57 deletions(-) diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index f3c6925b..ca3b7233 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -124,15 +124,15 @@ Designer + + + - {E1BD3C65-49C3-49E7-BABA-C60980CB3F20} + {e1bd3c65-49c3-49e7-baba-c60980cb3f20} CommandLine - - - @@ -389,15 +389,7 @@ - - - - ..\..\packages\xunit.abstractions\lib\net35\xunit.abstractions.dll - True - True - - - + @@ -409,26 +401,10 @@ - - - - ..\..\packages\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll - True - True - - - + - - - - ..\..\packages\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll - True - True - - - + diff --git a/tests/CommandLine.Tests/project.json b/tests/CommandLine.Tests/project.json index 424a45a0..8d96e778 100644 --- a/tests/CommandLine.Tests/project.json +++ b/tests/CommandLine.Tests/project.json @@ -1,33 +1,14 @@ -{ +{ "version": "1.0.0-*", "description": "CommandLine.DotNet.Tests", - "dependencies": { - "xunit": "2.1.0", - "CommandLine": { - "target": "project" - } + "xunit": "2.1.0" }, - "testRunner": "xunit", - + "runtimes": { + "win": {} + }, "frameworks": { - "netcoreapp1.0": { - "buildOptions": { - "define": [ "PLATFORM_DOTNET", "SKIP_FSHARP" ], - "keyFile": "../../CommandLine.snk" - }, - "dependencies": { - "Microsoft.NETCore.App": { - "type": "platform", - "version": "1.0.0" - }, - "System.Reflection": "4.1.0", - "System.Reflection.TypeExtensions": "4.1.0", - "FluentAssertions": "4.2.2", - "dotnet-test-xunit": "2.2.0-*" - }, - "imports": [ "dotnet5.4", "dnxcore50", "portable-net451+win81" ] - } + ".NETFramework,Version=v4.5": {} } -} +} \ No newline at end of file From 2b63108745a4530dba292d440fda00bcbbee76a4 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 22:35:32 +1100 Subject: [PATCH 22/26] Fix invalid cast coverting bool to expected int Add unit tests for TypeConverter for scalars (only). Add DotSettings.user to .gitignore. --- .gitignore | 1 + src/CommandLine/Core/TypeConverter.cs | 2 +- .../CommandLine.Tests.csproj | 1 + .../Unit/Core/TypeConverterTests.cs | 67 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs diff --git a/.gitignore b/.gitignore index 7f2e43bd..eb52d2c0 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,5 @@ artifacts/* *.nuget.targets *.lock.json *.nuget.props +*.DotSettings.user diff --git a/src/CommandLine/Core/TypeConverter.cs b/src/CommandLine/Core/TypeConverter.cs index 2cec8ada..ad2b7d81 100644 --- a/src/CommandLine/Core/TypeConverter.cs +++ b/src/CommandLine/Core/TypeConverter.cs @@ -84,7 +84,7 @@ private static Result ChangeTypeScalarImpl(string value, Type return (value == null) ? empty() : withValue(); }; - return value.IsBooleanString() + return value.IsBooleanString() && conversionType == typeof(bool) ? value.ToBoolean() : conversionType.GetTypeInfo().IsEnum ? value.ToEnum(conversionType, ignoreValueCase) : safeChangeType(); }; diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index ca3b7233..74e333be 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -112,6 +112,7 @@ Code + diff --git a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs new file mode 100644 index 00000000..8e1605b9 --- /dev/null +++ b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs @@ -0,0 +1,67 @@ +using System; +using System.CodeDom; +using System.Collections.Generic; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommandLine.Core; +using CSharpx; +using FluentAssertions; +using Xunit; + +namespace CommandLine.Tests.Unit.Core +{ + public class TypeConverterTests + { + [Theory] + [MemberData("ChangeType_scalars_source")] + public void ChangeType_scalars(string testValue, Type destinationType, CultureInfo culture, bool expectFail, object expectedResult) + { + Maybe result = TypeConverter.ChangeType(new[] {testValue}, destinationType, true, culture, true); + + if (expectFail) + { + result.MatchNothing().Should().BeTrue(); + } + else + { + object matchedValue; + + result.MatchJust(out matchedValue).Should().BeTrue(); + Assert.Equal(matchedValue, expectedResult); + } + } + + public static IEnumerable ChangeType_scalars_source + { + get + { + yield return new object[] { "1", typeof (int), CultureInfo.InvariantCulture, false, 1}; + yield return new object[] { "0", typeof (int), CultureInfo.InvariantCulture, false, 0 }; + yield return new object[] { "-1", typeof (int), CultureInfo.InvariantCulture, false, -1 }; + yield return new object[] { "1.0", typeof (int), CultureInfo.InvariantCulture, true, null }; + yield return new object[] { "1.0", typeof(float), CultureInfo.InvariantCulture, false, 1.0f }; + yield return new object[] { "0.0", typeof (float), CultureInfo.InvariantCulture, false, 0.0f}; + yield return new object[] { "-1.0", typeof (float), CultureInfo.InvariantCulture, false, -1.0f}; + yield return new object[] { "1.0", typeof(double), CultureInfo.InvariantCulture, false, 1.0 }; + yield return new object[] { "0.0", typeof (double), CultureInfo.InvariantCulture, false, 0.0}; + yield return new object[] { "-1.0", typeof(double), CultureInfo.InvariantCulture, false, -1.0 }; + yield return new object[] { "1.0", typeof(decimal), CultureInfo.InvariantCulture, false, 1.0m }; + yield return new object[] { "0.0", typeof(decimal), CultureInfo.InvariantCulture, false, 0.0m }; + yield return new object[] { "-1.0", typeof(decimal), CultureInfo.InvariantCulture, false, -1.0m }; + yield return new object[] { "-1.123456", typeof(decimal), CultureInfo.InvariantCulture, false, -1.123456m }; + yield return new object[] { "true", typeof(bool), CultureInfo.InvariantCulture, false, true }; + yield return new object[] { "false", typeof (bool), CultureInfo.InvariantCulture, false, false }; + yield return new object[] { "", typeof(string), CultureInfo.InvariantCulture, false, "" }; + yield return new object[] { "abcd", typeof(int), CultureInfo.InvariantCulture, true, "abcd" }; + yield return new object[] { "abcd", typeof(string), CultureInfo.InvariantCulture, false, "abcd" }; + + // Failed before change + yield return new object[] { "false", typeof(int), CultureInfo.InvariantCulture, true, 0 }; + yield return new object[] { "true", typeof(int), CultureInfo.InvariantCulture, true, 0 }; + } + } + } +} From 9146a74175717c5ff32dfb3f5a66cdb5fd129498 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 22:58:22 +1100 Subject: [PATCH 23/26] Expand tests --- .../Unit/Core/TypeConverterTests.cs | 77 +++++++++++++------ 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs index 8e1605b9..22a594a4 100644 --- a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs @@ -17,19 +17,19 @@ public class TypeConverterTests { [Theory] [MemberData("ChangeType_scalars_source")] - public void ChangeType_scalars(string testValue, Type destinationType, CultureInfo culture, bool expectFail, object expectedResult) + public void ChangeType_scalars(string testValue, Type destinationType, bool expectFail, object expectedResult) { - Maybe result = TypeConverter.ChangeType(new[] {testValue}, destinationType, true, culture, true); + Maybe result = TypeConverter.ChangeType(new[] {testValue}, destinationType, true, CultureInfo.InvariantCulture, true); if (expectFail) { - result.MatchNothing().Should().BeTrue(); + result.MatchNothing().Should().BeTrue("should fail parsing"); } else { object matchedValue; - result.MatchJust(out matchedValue).Should().BeTrue(); + result.MatchJust(out matchedValue).Should().BeTrue("should parse successfully"); Assert.Equal(matchedValue, expectedResult); } } @@ -38,29 +38,56 @@ public static IEnumerable ChangeType_scalars_source { get { - yield return new object[] { "1", typeof (int), CultureInfo.InvariantCulture, false, 1}; - yield return new object[] { "0", typeof (int), CultureInfo.InvariantCulture, false, 0 }; - yield return new object[] { "-1", typeof (int), CultureInfo.InvariantCulture, false, -1 }; - yield return new object[] { "1.0", typeof (int), CultureInfo.InvariantCulture, true, null }; - yield return new object[] { "1.0", typeof(float), CultureInfo.InvariantCulture, false, 1.0f }; - yield return new object[] { "0.0", typeof (float), CultureInfo.InvariantCulture, false, 0.0f}; - yield return new object[] { "-1.0", typeof (float), CultureInfo.InvariantCulture, false, -1.0f}; - yield return new object[] { "1.0", typeof(double), CultureInfo.InvariantCulture, false, 1.0 }; - yield return new object[] { "0.0", typeof (double), CultureInfo.InvariantCulture, false, 0.0}; - yield return new object[] { "-1.0", typeof(double), CultureInfo.InvariantCulture, false, -1.0 }; - yield return new object[] { "1.0", typeof(decimal), CultureInfo.InvariantCulture, false, 1.0m }; - yield return new object[] { "0.0", typeof(decimal), CultureInfo.InvariantCulture, false, 0.0m }; - yield return new object[] { "-1.0", typeof(decimal), CultureInfo.InvariantCulture, false, -1.0m }; - yield return new object[] { "-1.123456", typeof(decimal), CultureInfo.InvariantCulture, false, -1.123456m }; - yield return new object[] { "true", typeof(bool), CultureInfo.InvariantCulture, false, true }; - yield return new object[] { "false", typeof (bool), CultureInfo.InvariantCulture, false, false }; - yield return new object[] { "", typeof(string), CultureInfo.InvariantCulture, false, "" }; - yield return new object[] { "abcd", typeof(int), CultureInfo.InvariantCulture, true, "abcd" }; - yield return new object[] { "abcd", typeof(string), CultureInfo.InvariantCulture, false, "abcd" }; + yield return new object[] { "1", typeof (int), false, 1}; + yield return new object[] { "0", typeof (int), false, 0 }; + yield return new object[] { "-1", typeof (int), false, -1 }; + yield return new object[] { "abcd", typeof(int), true, null }; + yield return new object[] { "1.0", typeof(int), true, null }; + yield return new object[] { int.MaxValue.ToString(), typeof(int), false, int.MaxValue }; + yield return new object[] { int.MinValue.ToString(), typeof(int), false, int.MinValue }; + yield return new object[] { ((long)int.MaxValue + 1).ToString(), typeof(int), true, null }; + yield return new object[] { ((long)int.MinValue - 1).ToString(), typeof(int), true, null }; + + yield return new object[] { "1", typeof(uint), false, (uint) 1 }; + yield return new object[] { "0", typeof(uint), false, (uint) 0 }; + yield return new object[] { "-1", typeof(uint), true, null }; + yield return new object[] { uint.MaxValue.ToString(), typeof(uint), false, uint.MaxValue }; + yield return new object[] { uint.MinValue.ToString(), typeof(uint), false, uint.MinValue }; + yield return new object[] { ((long)uint.MaxValue + 1).ToString(), typeof(uint), true, null }; + yield return new object[] { ((long)uint.MinValue - 1).ToString(), typeof(uint), true, null }; + + yield return new object[] { "true", typeof(bool), false, true }; + yield return new object[] { "True", typeof(bool), false, true }; + yield return new object[] { "TRUE", typeof(bool), false, true }; + yield return new object[] { "false", typeof(bool), false, false }; + yield return new object[] { "False", typeof(bool), false, false }; + yield return new object[] { "FALSE", typeof(bool), false, false }; + yield return new object[] { "abcd", typeof(bool), true, null }; + yield return new object[] { "0", typeof(bool), true, null }; + yield return new object[] { "1", typeof(bool), true, null }; + + yield return new object[] { "1.0", typeof(float), false, 1.0f }; + yield return new object[] { "0.0", typeof (float), false, 0.0f}; + yield return new object[] { "-1.0", typeof (float), false, -1.0f}; + yield return new object[] { "abcd", typeof(float), true, null }; + + yield return new object[] { "1.0", typeof(double), false, 1.0 }; + yield return new object[] { "0.0", typeof (double), false, 0.0}; + yield return new object[] { "-1.0", typeof(double), false, -1.0 }; + yield return new object[] { "abcd", typeof(double), true, null }; + + yield return new object[] { "1.0", typeof(decimal), false, 1.0m }; + yield return new object[] { "0.0", typeof(decimal), false, 0.0m }; + yield return new object[] { "-1.0", typeof(decimal), false, -1.0m }; + yield return new object[] { "-1.123456", typeof(decimal), false, -1.123456m }; + yield return new object[] { "abcd", typeof(decimal), true, null }; + + yield return new object[] { "", typeof(string), false, "" }; + yield return new object[] { "abcd", typeof(string), false, "abcd" }; // Failed before change - yield return new object[] { "false", typeof(int), CultureInfo.InvariantCulture, true, 0 }; - yield return new object[] { "true", typeof(int), CultureInfo.InvariantCulture, true, 0 }; + yield return new object[] { "false", typeof(int), true, 0 }; + yield return new object[] { "true", typeof(int), true, 0 }; } } } From 977b7546ec53b77c57e08c81a4227ee65486a4d2 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 23:02:11 +1100 Subject: [PATCH 24/26] Convert from yield return to object[][] --- .../Unit/Core/TypeConverterTests.cs | 89 ++++++++++--------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs index 22a594a4..4effd933 100644 --- a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs @@ -38,56 +38,59 @@ public static IEnumerable ChangeType_scalars_source { get { - yield return new object[] { "1", typeof (int), false, 1}; - yield return new object[] { "0", typeof (int), false, 0 }; - yield return new object[] { "-1", typeof (int), false, -1 }; - yield return new object[] { "abcd", typeof(int), true, null }; - yield return new object[] { "1.0", typeof(int), true, null }; - yield return new object[] { int.MaxValue.ToString(), typeof(int), false, int.MaxValue }; - yield return new object[] { int.MinValue.ToString(), typeof(int), false, int.MinValue }; - yield return new object[] { ((long)int.MaxValue + 1).ToString(), typeof(int), true, null }; - yield return new object[] { ((long)int.MinValue - 1).ToString(), typeof(int), true, null }; + return new[] + { + new object[] {"1", typeof (int), false, 1}, + new object[] {"0", typeof (int), false, 0}, + new object[] {"-1", typeof (int), false, -1}, + new object[] {"abcd", typeof (int), true, null}, + new object[] {"1.0", typeof (int), true, null}, + new object[] {int.MaxValue.ToString(), typeof (int), false, int.MaxValue}, + new object[] {int.MinValue.ToString(), typeof (int), false, int.MinValue}, + new object[] {((long) int.MaxValue + 1).ToString(), typeof (int), true, null}, + new object[] {((long) int.MinValue - 1).ToString(), typeof (int), true, null}, - yield return new object[] { "1", typeof(uint), false, (uint) 1 }; - yield return new object[] { "0", typeof(uint), false, (uint) 0 }; - yield return new object[] { "-1", typeof(uint), true, null }; - yield return new object[] { uint.MaxValue.ToString(), typeof(uint), false, uint.MaxValue }; - yield return new object[] { uint.MinValue.ToString(), typeof(uint), false, uint.MinValue }; - yield return new object[] { ((long)uint.MaxValue + 1).ToString(), typeof(uint), true, null }; - yield return new object[] { ((long)uint.MinValue - 1).ToString(), typeof(uint), true, null }; + new object[] {"1", typeof (uint), false, (uint) 1}, + new object[] {"0", typeof (uint), false, (uint) 0}, + new object[] {"-1", typeof (uint), true, null}, + new object[] {uint.MaxValue.ToString(), typeof (uint), false, uint.MaxValue}, + new object[] {uint.MinValue.ToString(), typeof (uint), false, uint.MinValue}, + new object[] {((long) uint.MaxValue + 1).ToString(), typeof (uint), true, null}, + new object[] {((long) uint.MinValue - 1).ToString(), typeof (uint), true, null}, - yield return new object[] { "true", typeof(bool), false, true }; - yield return new object[] { "True", typeof(bool), false, true }; - yield return new object[] { "TRUE", typeof(bool), false, true }; - yield return new object[] { "false", typeof(bool), false, false }; - yield return new object[] { "False", typeof(bool), false, false }; - yield return new object[] { "FALSE", typeof(bool), false, false }; - yield return new object[] { "abcd", typeof(bool), true, null }; - yield return new object[] { "0", typeof(bool), true, null }; - yield return new object[] { "1", typeof(bool), true, null }; + new object[] {"true", typeof (bool), false, true}, + new object[] {"True", typeof (bool), false, true}, + new object[] {"TRUE", typeof (bool), false, true}, + new object[] {"false", typeof (bool), false, false}, + new object[] {"False", typeof (bool), false, false}, + new object[] {"FALSE", typeof (bool), false, false}, + new object[] {"abcd", typeof (bool), true, null}, + new object[] {"0", typeof (bool), true, null}, + new object[] {"1", typeof (bool), true, null}, - yield return new object[] { "1.0", typeof(float), false, 1.0f }; - yield return new object[] { "0.0", typeof (float), false, 0.0f}; - yield return new object[] { "-1.0", typeof (float), false, -1.0f}; - yield return new object[] { "abcd", typeof(float), true, null }; + new object[] {"1.0", typeof (float), false, 1.0f}, + new object[] {"0.0", typeof (float), false, 0.0f}, + new object[] {"-1.0", typeof (float), false, -1.0f}, + new object[] {"abcd", typeof (float), true, null}, - yield return new object[] { "1.0", typeof(double), false, 1.0 }; - yield return new object[] { "0.0", typeof (double), false, 0.0}; - yield return new object[] { "-1.0", typeof(double), false, -1.0 }; - yield return new object[] { "abcd", typeof(double), true, null }; + new object[] {"1.0", typeof (double), false, 1.0}, + new object[] {"0.0", typeof (double), false, 0.0}, + new object[] {"-1.0", typeof (double), false, -1.0}, + new object[] {"abcd", typeof (double), true, null}, - yield return new object[] { "1.0", typeof(decimal), false, 1.0m }; - yield return new object[] { "0.0", typeof(decimal), false, 0.0m }; - yield return new object[] { "-1.0", typeof(decimal), false, -1.0m }; - yield return new object[] { "-1.123456", typeof(decimal), false, -1.123456m }; - yield return new object[] { "abcd", typeof(decimal), true, null }; + new object[] {"1.0", typeof (decimal), false, 1.0m}, + new object[] {"0.0", typeof (decimal), false, 0.0m}, + new object[] {"-1.0", typeof (decimal), false, -1.0m}, + new object[] {"-1.123456", typeof (decimal), false, -1.123456m}, + new object[] {"abcd", typeof (decimal), true, null}, - yield return new object[] { "", typeof(string), false, "" }; - yield return new object[] { "abcd", typeof(string), false, "abcd" }; + new object[] {"", typeof (string), false, ""}, + new object[] {"abcd", typeof (string), false, "abcd"}, - // Failed before change - yield return new object[] { "false", typeof(int), true, 0 }; - yield return new object[] { "true", typeof(int), true, 0 }; + // Failed before #339 + new object[] {"false", typeof (int), true, 0}, + new object[] {"true", typeof (int), true, 0} + }; } } } From 6ba656eed29bb811b719fbfa2d2776309f7aecb3 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 23:09:39 +1100 Subject: [PATCH 25/26] More tests --- .../Unit/Core/TypeConverterTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs index 4effd933..7642a80a 100644 --- a/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TypeConverterTests.cs @@ -15,6 +15,12 @@ namespace CommandLine.Tests.Unit.Core { public class TypeConverterTests { + enum TestEnum + { + ValueA = 1, + ValueB = 2 + } + [Theory] [MemberData("ChangeType_scalars_source")] public void ChangeType_scalars(string testValue, Type destinationType, bool expectFail, object expectedResult) @@ -87,6 +93,14 @@ public static IEnumerable ChangeType_scalars_source new object[] {"", typeof (string), false, ""}, new object[] {"abcd", typeof (string), false, "abcd"}, + new object[] {"ValueA", typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {"VALUEA", typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {"ValueB", typeof(TestEnum), false, TestEnum.ValueB}, + new object[] {((int) TestEnum.ValueA).ToString(), typeof (TestEnum), false, TestEnum.ValueA}, + new object[] {((int) TestEnum.ValueB).ToString(), typeof (TestEnum), false, TestEnum.ValueB}, + new object[] {((int) TestEnum.ValueB + 1).ToString(), typeof (TestEnum), true, null}, + new object[] {((int) TestEnum.ValueA - 1).ToString(), typeof (TestEnum), true, null}, + // Failed before #339 new object[] {"false", typeof (int), true, 0}, new object[] {"true", typeof (int), true, 0} From 8b318925d593589bca1d49ebc8510119bd2e5f44 Mon Sep 17 00:00:00 2001 From: Anthony Langsworth Date: Fri, 7 Oct 2016 23:13:02 +1100 Subject: [PATCH 26/26] Reverse local build changes for CI --- .../CommandLine.Tests.csproj | 38 +++++++++++++++---- tests/CommandLine.Tests/project.json | 33 ++++++++++++---- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/tests/CommandLine.Tests/CommandLine.Tests.csproj b/tests/CommandLine.Tests/CommandLine.Tests.csproj index 74e333be..dfcc5c1e 100644 --- a/tests/CommandLine.Tests/CommandLine.Tests.csproj +++ b/tests/CommandLine.Tests/CommandLine.Tests.csproj @@ -125,15 +125,15 @@ Designer - - - - {e1bd3c65-49c3-49e7-baba-c60980cb3f20} + {E1BD3C65-49C3-49E7-BABA-C60980CB3F20} CommandLine + + + @@ -390,7 +390,15 @@ - + + + + ..\..\packages\xunit.abstractions\lib\net35\xunit.abstractions.dll + True + True + + + @@ -402,10 +410,26 @@ - + + + + ..\..\packages\xunit.assert\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.assert.dll + True + True + + + - + + + + ..\..\packages\xunit.extensibility.core\lib\portable-net45+win+wpa81+wp80+monotouch+monoandroid+Xamarin.iOS\xunit.core.dll + True + True + + + diff --git a/tests/CommandLine.Tests/project.json b/tests/CommandLine.Tests/project.json index 8d96e778..424a45a0 100644 --- a/tests/CommandLine.Tests/project.json +++ b/tests/CommandLine.Tests/project.json @@ -1,14 +1,33 @@ -{ +{ "version": "1.0.0-*", "description": "CommandLine.DotNet.Tests", + "dependencies": { - "xunit": "2.1.0" + "xunit": "2.1.0", + "CommandLine": { + "target": "project" + } }, + "testRunner": "xunit", - "runtimes": { - "win": {} - }, + "frameworks": { - ".NETFramework,Version=v4.5": {} + "netcoreapp1.0": { + "buildOptions": { + "define": [ "PLATFORM_DOTNET", "SKIP_FSHARP" ], + "keyFile": "../../CommandLine.snk" + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0" + }, + "System.Reflection": "4.1.0", + "System.Reflection.TypeExtensions": "4.1.0", + "FluentAssertions": "4.2.2", + "dotnet-test-xunit": "2.2.0-*" + }, + "imports": [ "dotnet5.4", "dnxcore50", "portable-net451+win81" ] + } } -} \ No newline at end of file +}