Skip to content

Commit dd25e30

Browse files
authored
Merge pull request #453 from moh-hassan/fix/null-enum
Fix issue #104 of nullable enum
2 parents 16ca79c + c53acce commit dd25e30

File tree

4 files changed

+99
-8
lines changed

4 files changed

+99
-8
lines changed

src/CommandLine/Core/Specification.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.Linq;
66
using System.Reflection;
7+
using CommandLine.Infrastructure;
78
using CSharpx;
89

910
namespace CommandLine.Core
@@ -115,9 +116,8 @@ public static Specification FromProperty(PropertyInfo property)
115116
if (oa.Count() == 1)
116117
{
117118
var spec = OptionSpecification.FromAttribute(oa.Single(), property.PropertyType,
118-
property.PropertyType.GetTypeInfo().IsEnum
119-
? Enum.GetNames(property.PropertyType)
120-
: Enumerable.Empty<string>());
119+
ReflectionHelper.GetNamesOfEnum(property.PropertyType));
120+
121121
if (spec.ShortName.Length == 0 && spec.LongName.Length == 0)
122122
{
123123
return spec.WithLongName(property.Name.ToLowerInvariant());

src/CommandLine/Infrastructure/ReflectionHelper.cs

+15-5
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ public static Maybe<TAttribute> GetAttribute<TAttribute>()
4545
// Test support
4646
if (_overrides != null)
4747
{
48-
return
48+
return
4949
_overrides.ContainsKey(typeof(TAttribute)) ?
5050
Maybe.Just((TAttribute)_overrides[typeof(TAttribute)]) :
51-
Maybe.Nothing< TAttribute>();
51+
Maybe.Nothing<TAttribute>();
5252
}
5353

5454
var assembly = GetExecutingOrEntryAssembly();
@@ -84,7 +84,7 @@ public static bool IsFSharpOptionType(Type type)
8484

8585
public static T CreateDefaultImmutableInstance<T>(Type[] constructorTypes)
8686
{
87-
var t = typeof(T);
87+
var t = typeof(T);
8888
return (T)CreateDefaultImmutableInstance(t, constructorTypes);
8989
}
9090

@@ -100,7 +100,17 @@ private static Assembly GetExecutingOrEntryAssembly()
100100
{
101101
//resolve issues of null EntryAssembly in Xunit Test #392,424,389
102102
//return Assembly.GetEntryAssembly();
103-
return Assembly.GetEntryAssembly()??Assembly.GetCallingAssembly();
103+
return Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
104+
}
105+
106+
public static IEnumerable<string> GetNamesOfEnum(Type t)
107+
{
108+
if (t.IsEnum)
109+
return Enum.GetNames(t);
110+
Type u = Nullable.GetUnderlyingType(t);
111+
if (u != null && u.IsEnum)
112+
return Enum.GetNames(u);
113+
return Enumerable.Empty<string>();
104114
}
105115
}
106-
}
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
2+
3+
namespace CommandLine.Tests.Fakes
4+
{
5+
class Options_With_Nullable_Enum_Having_HelpText
6+
{
7+
[Option(HelpText = "Define a string value here.")]
8+
public string StringValue { get; set; }
9+
10+
[Option(HelpText="Define a enum value here.")]
11+
public Shapes? Shape { get; set; }
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System.Linq;
2+
using CommandLine.Tests.Fakes;
3+
using CommandLine.Text;
4+
using FluentAssertions;
5+
using Xunit;
6+
using Xunit.Abstractions;
7+
8+
//Issue #104
9+
//When outputting HelpText, the code will correctly list valid values for enum type options. However, if the option is a nullable enum type, then it will not list the valid values.
10+
11+
namespace CommandLine.Tests.Unit
12+
{
13+
public class Issue104Tests
14+
{
15+
16+
[Fact]
17+
public void Create_instance_with_enum_options_enabled_and_nullable_enum()
18+
{
19+
// Fixture setup
20+
// Exercize system
21+
var sut = new HelpText { AddDashesToOption = true, AddEnumValuesToHelpText = true, MaximumDisplayWidth = 80 }
22+
.AddPreOptionsLine("pre-options")
23+
.AddOptions(new NotParsed<Options_With_Nullable_Enum_Having_HelpText>(TypeInfo.Create(typeof(Options_With_Enum_Having_HelpText)), Enumerable.Empty<Error>()))
24+
.AddPostOptionsLine("post-options");
25+
26+
// Verify outcome
27+
28+
var lines = sut.ToString().ToNotEmptyLines().TrimStringArray();
29+
lines[0].Should().BeEquivalentTo("pre-options");
30+
lines[1].Should().BeEquivalentTo("--stringvalue Define a string value here.");
31+
lines[2].Should().BeEquivalentTo("--shape Define a enum value here. Valid values: Circle, Square,");
32+
lines[3].Should().BeEquivalentTo("Triangle");
33+
lines[4].Should().BeEquivalentTo("--help Display this help screen.");
34+
lines[5].Should().BeEquivalentTo("--version Display version information.");
35+
lines[6].Should().BeEquivalentTo("post-options");
36+
// Teardown
37+
}
38+
39+
[Fact]
40+
public void Help_with_enum_options_enabled_and_nullable_enum()
41+
{
42+
// Fixture setup
43+
// Exercize system
44+
var args = "--help".Split();
45+
var sut = new Parser(config => config.HelpWriter = null);
46+
var parserResult = sut.ParseArguments<Options_With_Nullable_Enum_Having_HelpText>(args);
47+
HelpText helpText = null;
48+
parserResult.WithNotParsed(errors =>
49+
{
50+
// Use custom help text to ensure valid enum values are displayed
51+
helpText = HelpText.AutoBuild(parserResult);
52+
helpText.AddEnumValuesToHelpText = true;
53+
helpText.AddOptions(parserResult);
54+
});
55+
56+
// Verify outcome
57+
58+
var lines = helpText.ToString().ToNotEmptyLines().TrimStringArray();
59+
lines[2].Should().BeEquivalentTo("--stringvalue Define a string value here.");
60+
lines[3].Should().BeEquivalentTo("--shape Define a enum value here. Valid values: Circle, Square,");
61+
lines[4].Should().BeEquivalentTo("Triangle");
62+
lines[5].Should().BeEquivalentTo("--help Display this help screen.");
63+
lines[6].Should().BeEquivalentTo("--version Display version information.");
64+
// Teardown
65+
}
66+
}
67+
68+
}

0 commit comments

Comments
 (0)