Browse files

Add support for nullable types to OptionSet.Add().

This allows straightforward use of nullable types, e.g.

		int verbosity = 0;
		new OptionSet () {
			{ "v:", (int? v) => verbosity = v.HasValue
				? v.Value : verbosity + 1 },
		}.Parse (new[]{"-v"); // verbosity == 1

	* Makefile.am: Specify NDESK_OPTIONS on the compile lines.
	* doc/en/NDesk.Options/OptionSet.xml: Document nullable type support.
	* lib/pkgconfig/ndesk-options.pc.in: Add -d:NDESK_OPTIONS so that
	  packages using prior versions of NDesk.Options don't see a
	  gratuitous namespace change.
	* src/NDesk.Options/NDesk.Options/Options.cs: Option.Parse<T>() now
	  special-cases nullable type conversion.
	* src/NDesk.Options/NDesk.Options/Options.cs,
	  src/NDesk.Options/Test/NDesk.Options/OptionContextTest.cs,
	  src/NDesk.Options/Test/NDesk.Options/OptionSetTest.cs,
	  src/NDesk.Options/Test/NDesk.Options/OptionTest.cs,
	  src/NDesk.Options/Test/NDesk.Options/Utils.cs: Namespace
	  "harmonization" with Mono.Options, so that we can use identical
	  source in each place, thus minimizing the maintenance burden.
  • Loading branch information...
1 parent 6894457 commit 184cd420db2dfa03b0c20dfafd449ee82f357892 @jonpryor jonpryor committed Oct 23, 2008
View
6 Makefile.am
@@ -41,19 +41,19 @@ dist-hook:
$(nolibdir)/NDesk.Options.dll: $(OPTIONS_SRC)
-mkdir -p `dirname $@`
- $(CSC) -debug+ $(OPTIONS_SRC) -langversion:ISO-2 -t:library -out:$@
+ $(CSC) -debug+ -d:NDESK_OPTIONS $(OPTIONS_SRC) -langversion:ISO-2 -t:library -out:$@
$(nolibdir)/NDesk.Options_test.dll: $(nolibdir)/NDesk.Options.dll $(OPTIONS_TEST_SRC)
-mkdir -p `dirname $@`
$(CSC) -debug+ -t:library -out:$@ -r:$(nolibdir)/NDesk.Options.dll \
-r:nunit.core.dll -r:nunit.framework.dll -r:nunit.util.dll \
- $(OPTIONS_TEST_SRC)
+ -d:NDESK_OPTIONS $(OPTIONS_TEST_SRC)
$(nolibdir)/NDesk.Options_test_linq.dll: $(OPTIONS_SRC) $(OPTIONS_TEST_SRC)
-mkdir -p `dirname $@`
$(CSC) -debug+ -d:LINQ -t:library -out:$@ \
-r:nunit.core.dll -r:nunit.framework.dll -r:nunit.util.dll \
- $(OPTIONS_SRC) $(OPTIONS_TEST_SRC)
+ -d:NDESK_OPTIONS $(OPTIONS_SRC) $(OPTIONS_TEST_SRC)
check: $(nolibdir)/NDesk.Options_test.dll $(nolibdir)/NDesk.Options_test_linq.dll
nunit-console2 $(nolibdir)/NDesk.Options_test.dll
View
11 doc/en/NDesk.Options/OptionSet.xml
@@ -1412,6 +1412,17 @@ localization: hello:Could not convert string `not-an-int' to type Int32 for opti
<see cref="T:System.ComponentModel.TypeConverter" /> to use when
performing the string-to-type conversion.
</para>
+ <para>
+ Special support is provided for <see cref="T:System.Nullable{X}" />
+ types; <see cref="T:System.ComponentModel.TypeConverter" />
+ doesn't currently support their use, but if
+ <typeparamref name="T" /> is a nullable type, then this method
+ will instead use the
+ <see cref="T:System.ComponentModel.TypeConverter" /> for the
+ <typeparamref name="X" /> type. This allows straightforward use
+ of nullable types, identical to using any other strongly typed
+ value.
+ </para>
<block subset="none" type="note">
<para>
If <paramref name="prototype" /> specifies an
View
2 lib/pkgconfig/ndesk-options.pc.in
@@ -9,4 +9,4 @@ Name: NDesk.Options
Description: C# Program Option Parsing Library.
Version: @VERSION@
Requires:
-Libs: -r:NDesk.Options.dll
+Libs: -d:NDESK_OPTIONS -r:NDesk.Options.dll
View
15 src/NDesk.Options/NDesk.Options/Options.cs
@@ -143,8 +143,12 @@
using NDesk.Options;
#endif
-namespace NDesk.Options {
-
+#if NDESK_OPTIONS
+namespace NDesk.Options
+#else
+namespace Mono.Options
+#endif
+{
public class OptionValueCollection : IList, IList<string> {
List<string> values = new List<string> ();
@@ -341,7 +345,12 @@ public string[] GetValueSeparators ()
protected static T Parse<T> (string value, OptionContext c)
{
- TypeConverter conv = TypeDescriptor.GetConverter (typeof (T));
+ Type tt = typeof (T);
+ bool nullable = tt.IsValueType && tt.IsGenericType &&
+ !tt.IsGenericTypeDefinition &&
+ tt.GetGenericTypeDefinition () == typeof (Nullable<>);
+ Type targetType = nullable ? tt.GetGenericArguments () [0] : typeof (T);
+ TypeConverter conv = TypeDescriptor.GetConverter (targetType);
T t = default (T);
try {
if (value != null)
View
12 src/NDesk.Options/Test/NDesk.Options/OptionContextTest.cs
@@ -28,10 +28,20 @@
using System;
+#if NDESK_OPTIONS
using NDesk.Options;
+#else
+using Mono.Options
+#endif
+
using NUnit.Framework;
-namespace Tests.NDesk.Options {
+#if NDESK_OPTIONS
+namespace Tests.NDesk.Options
+#else
+namespace Tests.Mono.Options
+#endif
+{
[TestFixture]
public class OptionContextTest {
[Test]
View
25 src/NDesk.Options/Test/NDesk.Options/OptionSetTest.cs
@@ -32,11 +32,20 @@
using System.Globalization;
using System.IO;
+#if NDESK_OPTIONS
using NDesk.Options;
-using NUnit.Framework;
+#else
+using Mono.Options
+#endif
-namespace Tests.NDesk.Options {
+using NUnit.Framework;
+#if NDESK_OPTIONS
+namespace Tests.NDesk.Options
+#else
+namespace Tests.Mono.Options
+#endif
+{
class FooConverter : TypeConverter {
public override bool CanConvertFrom (ITypeDescriptorContext context, Type sourceType)
{
@@ -128,11 +137,11 @@ public void RequiredValues ()
public void OptionalValues ()
{
string a = null;
- int n = -1;
+ int? n = -1;
Foo f = null;
OptionSet p = new OptionSet () {
{ "a:", v => a = v },
- { "n:", (int v) => n = v },
+ { "n:", (int? v) => n = v },
{ "f:", (Foo v) => f = v },
};
p.Parse (_("-a=s"));
@@ -153,13 +162,13 @@ public void OptionalValues ()
Assert.AreEqual (f, Foo.A);
p.Parse (_("-n42"));
- Assert.AreEqual (n, 42);
+ Assert.AreEqual (n.Value, 42);
p.Parse (_("-n", "42"));
- Assert.AreEqual (n, 0);
+ Assert.AreEqual (n.HasValue, false);
p.Parse (_("-n=42"));
- Assert.AreEqual (n, 42);
+ Assert.AreEqual (n.Value, 42);
p.Parse (_("-n"));
- Assert.AreEqual (n, 0);
+ Assert.AreEqual (n.HasValue, false);
}
[Test]
View
12 src/NDesk.Options/Test/NDesk.Options/OptionTest.cs
@@ -28,10 +28,20 @@
using System;
+#if NDESK_OPTIONS
using NDesk.Options;
+#else
+using Mono.Options
+#endif
+
using NUnit.Framework;
-namespace Tests.NDesk.Options {
+#if NDESK_OPTIONS
+namespace Tests.NDesk.Options
+#else
+namespace Tests.Mono.Options
+#endif
+{
class DefaultOption : Option {
public DefaultOption (string prototypes, string description)
: base (prototypes, description)
View
7 src/NDesk.Options/Test/NDesk.Options/Utils.cs
@@ -28,7 +28,12 @@
using System;
-namespace Tests.NDesk.Options {
+#if NDESK_OPTIONS
+namespace Tests.NDesk.Options
+#else
+namespace Tests.Mono.Options
+#endif
+{
static class Utils {
public static void AssertException<T> (Type exception, string message, T a, Action<T> action)
{

0 comments on commit 184cd42

Please sign in to comment.