Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/libcmdline/Attributes/OptionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@ namespace CommandLine
/// <summary>
/// Models an option specification.
/// </summary>
[AttributeUsage(AttributeTargets.Field,
AllowMultiple=false,
Inherited=true)]
[AttributeUsage(AttributeTargets.Property , AllowMultiple=false, Inherited=true)]
public class OptionAttribute : BaseOptionAttribute
{
private string _uniqueName;
private readonly string _uniqueName;
private string _mutuallyExclusiveSet;

internal const string DefaultMutuallyExclusiveSet = "Default";
Expand Down
35 changes: 16 additions & 19 deletions src/libcmdline/Attributes/Tests/HelpOptionAttributeFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#if UNIT_TESTS
#region Using Directives
using System;
using System.ComponentModel;
using System.IO;
using CommandLine.Text;
using NUnit.Framework;
Expand All @@ -42,25 +43,21 @@ public sealed class HelpOptionAttributeFixture : CommandLineParserBaseFixture
#region Mock Objects
private class MockOptions
{
[Option("i", "input",
Required=true,
HelpText="Input file with equations, xml format (see manual).")]
public string InputFile = null;

[Option("o", "output",
Required=false,
HelpText="Output file with results, otherwise standard output.")]
public string OutputFile = null;

[Option(null, "paralell",
Required=false,
HelpText="Paralellize processing in multiple threads.")]
public bool ParalellizeProcessing = false;

[Option("v", null,
Required=false,
HelpText="Show detailed processing messages.")]
public bool Verbose = false;
[Option("i", "input", Required = true, HelpText = "Input file with equations, xml format (see manual).")]
[DefaultValue(null)]
public string InputFile { get; set; }

[Option("o", "output", Required=false, HelpText="Output file with results, otherwise standard output.")]
[DefaultValue(null)]
public string OutputFile {get;set;}

[Option(null, "paralell", Required=false, HelpText="Paralellize processing in multiple threads.")]
[DefaultValue(false)]
public bool ParalellizeProcessing{get;set;}

[Option("v", null, Required=false, HelpText="Show detailed processing messages.")]
[DefaultValue(false)]
public bool Verbose{get;set;}

[HelpOption(HelpText="Display this screen.")]
public string GetUsage()
Expand Down
4 changes: 3 additions & 1 deletion src/libcmdline/Attributes/Tests/ValueListAttributeFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#region Using Directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using NUnit.Framework;
#endregion

Expand All @@ -46,7 +47,8 @@ private class MockSpecializedList : List<string>
private class MockOptions
{
[ValueList(typeof(List<string>))]
public IList<string> Values = null;
[DefaultValue(null)]
public IList<string> Values { get; set; }
}
#endregion

Expand Down
22 changes: 11 additions & 11 deletions src/libcmdline/Attributes/ValueListAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ namespace CommandLine
/// Must be applied to a field compatible with an <see cref="System.Collections.Generic.IList&lt;T&gt;"/> interface
/// of <see cref="System.String"/> instances.
/// </summary>
[AttributeUsage(AttributeTargets.Field,
[AttributeUsage(AttributeTargets.Property,
AllowMultiple=false,
Inherited=true)]
public sealed class ValueListAttribute : Attribute
{
private Type _concreteType;
private readonly Type _concreteType;

private ValueListAttribute()
{
Expand Down Expand Up @@ -83,20 +83,20 @@ internal Type ConcreteType
internal static IList<string> GetReference(object target)
{
Type concreteType;
var field = GetField(target, out concreteType);
var property = GetProperty(target, out concreteType);

if (field == null)
if (property == null || concreteType == null)
return null;

field.SetValue(target, Activator.CreateInstance(concreteType));
property.SetValue(target, Activator.CreateInstance(concreteType), null);

return (IList<string>)field.GetValue(target);
return (IList<string>)property.GetValue(target, null);
}

internal static ValueListAttribute GetAttribute(object target)
{
var list = ReflectionUtil.RetrieveFieldList<ValueListAttribute>(target);
if (list.Count == 0)
var list = ReflectionUtil.RetrievePropertyList<ValueListAttribute>(target);
if (list == null || list.Count == 0)
return null;

if (list.Count > 1)
Expand All @@ -107,12 +107,12 @@ internal static ValueListAttribute GetAttribute(object target)
return pairZero.Right;
}

private static FieldInfo GetField(object target, out Type concreteType)
private static PropertyInfo GetProperty(object target, out Type concreteType)
{
concreteType = null;

var list = ReflectionUtil.RetrieveFieldList<ValueListAttribute>(target);
if (list.Count == 0)
var list = ReflectionUtil.RetrievePropertyList<ValueListAttribute>(target);
if (list == null || list.Count == 0)
return null;

if (list.Count > 1)
Expand Down
9 changes: 3 additions & 6 deletions src/libcmdline/CommandLine.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
Expand Down Expand Up @@ -38,7 +38,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;UNIT_TESTS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\CommandLine.XML</DocumentationFile>
Expand Down Expand Up @@ -201,8 +201,5 @@
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Folder Include="Parser\" />
<Folder Include="Parser\" />
</ItemGroup>
<ItemGroup />
</Project>
90 changes: 52 additions & 38 deletions src/libcmdline/Core/OptionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,32 @@ namespace CommandLine
sealed class OptionInfo
{
private readonly OptionAttribute _attribute;
private readonly FieldInfo _field;
private bool _required;
private string _helpText;
private string _shortName;
private string _longName;
private string _mutuallyExclusiveSet;

private object _setValueLock = new object();

public OptionInfo(OptionAttribute attribute, FieldInfo field)
private readonly PropertyInfo _property;
private readonly bool _required;
private readonly string _helpText;
private readonly string _shortName;
private readonly string _longName;
private readonly string _mutuallyExclusiveSet;
private readonly object _setValueLock = new object();

public OptionInfo(OptionAttribute attribute, PropertyInfo property)
{
_required = attribute.Required;
_helpText = attribute.HelpText;
_shortName = attribute.ShortName;
_longName = attribute.LongName;
_mutuallyExclusiveSet = attribute.MutuallyExclusiveSet;
_field = field;
_attribute = attribute;
if (attribute != null)
{
_required = attribute.Required;
_helpText = attribute.HelpText;
_shortName = attribute.ShortName;
_longName = attribute.LongName;
_mutuallyExclusiveSet = attribute.MutuallyExclusiveSet;
_attribute = attribute;
}
else
throw new ArgumentNullException("attribute", "The attribute is mandatory");

if (property != null)
_property = property;
else
throw new ArgumentNullException("property", "The property is mandatory");
}

#if UNIT_TESTS
Expand All @@ -70,33 +78,39 @@ internal OptionInfo(string shortName, string longName)
#endif
public static OptionMap CreateMap(object target, CommandLineParserSettings settings)
{
var list = ReflectionUtil.RetrieveFieldList<OptionAttribute>(target);
OptionMap map = new OptionMap(list.Count, settings);

foreach (Pair<FieldInfo, OptionAttribute> pair in list)
var list = ReflectionUtil.RetrievePropertyList<OptionAttribute>(target);
if (list != null)
{
map[pair.Right.UniqueName] = new OptionInfo(pair.Right, pair.Left);
}
var map = new OptionMap(list.Count, settings);

foreach (var pair in list)
{
if (pair != null && pair.Right != null)
map[pair.Right.UniqueName] = new OptionInfo(pair.Right, pair.Left);
}

map.RawOptions = target;

map.RawOptions = target;
return map;
}

return map;
return null;
}

public bool SetValue(string value, object options)
{
if (_attribute is OptionListAttribute)
return SetValueList(value, options);

if (ReflectionUtil.IsNullableType(_field.FieldType))
if (ReflectionUtil.IsNullableType(_property.PropertyType))
return SetNullableValue(value, options);

return SetValueScalar(value, options);
}

public bool SetValue(IList<string> values, object options)
{
Type elementType = _field.FieldType.GetElementType();
Type elementType = _property.PropertyType.GetElementType();
Array array = Array.CreateInstance(elementType, values.Count);

for (int i = 0; i < array.Length; i++)
Expand All @@ -106,7 +120,7 @@ public bool SetValue(IList<string> values, object options)
lock (_setValueLock)
{
array.SetValue(Convert.ChangeType(values[i], elementType, CultureInfo.InvariantCulture), i);
_field.SetValue(options, array);
_property.SetValue(options, array, null);
}
}
catch (FormatException)
Expand All @@ -122,18 +136,18 @@ private bool SetValueScalar(string value, object options)
{
try
{
if (_field.FieldType.IsEnum)
if (_property.PropertyType.IsEnum)
{
lock (_setValueLock)
{
_field.SetValue(options, Enum.Parse(_field.FieldType, value, true));
_property.SetValue(options, Enum.Parse(_property.PropertyType, value, true), null);
}
}
else
{
lock (_setValueLock)
{
_field.SetValue(options, Convert.ChangeType(value, _field.FieldType, CultureInfo.InvariantCulture));
_property.SetValue(options, Convert.ChangeType(value, _property.PropertyType, CultureInfo.InvariantCulture), null);
}
}
}
Expand All @@ -155,13 +169,13 @@ private bool SetValueScalar(string value, object options)

private bool SetNullableValue(string value, object options)
{
var nc = new NullableConverter(_field.FieldType);
var nc = new NullableConverter(_property.PropertyType);

try
{
lock (_setValueLock)
{
_field.SetValue(options, nc.ConvertFromString(null, CultureInfo.InvariantCulture, value));
_property.SetValue(options, nc.ConvertFromString(null, CultureInfo.InvariantCulture, value), null);
}
}
// the FormatException (thrown by ConvertFromString) is thrown as Exception.InnerException,
Expand All @@ -178,7 +192,7 @@ public bool SetValue(bool value, object options)
{
lock (_setValueLock)
{
_field.SetValue(options, value);
_property.SetValue(options, value, null);

return true;
}
Expand All @@ -188,9 +202,9 @@ private bool SetValueList(string value, object options)
{
lock (_setValueLock)
{
_field.SetValue(options, new List<string>());
_property.SetValue(options, new List<string>(), null);

var fieldRef = (IList<string>)_field.GetValue(options);
var fieldRef = (IList<string>)_property.GetValue(options, null);
var values = value.Split(((OptionListAttribute)_attribute).Separator);

for (int i = 0; i < values.Length; i++)
Expand Down Expand Up @@ -240,12 +254,12 @@ public string HelpText

public bool IsBoolean
{
get { return _field.FieldType == typeof(bool); }
get { return _property.PropertyType == typeof(bool); }
}

public bool IsArray
{
get { return _field.FieldType.IsArray; }
get { return _property.PropertyType.IsArray; }
}

public bool IsAttributeArrayCompatible
Expand Down
14 changes: 10 additions & 4 deletions src/libcmdline/Tests/Mocks/BooleanSetOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,28 @@
//
#endregion

using System.ComponentModel;

#if UNIT_TESTS
namespace CommandLine.Tests.Mocks
{
class BooleanSetOptions : OptionsBase
{
[Option("a", "option-a")]
public bool BooleanOne = false;
[DefaultValue(false)]
public bool BooleanOne { get; set; }

[Option("b", "option-b")]
public bool BooleanTwo = false;
[DefaultValue(false)]
public bool BooleanTwo { get; set; }

[Option("c", "option-c")]
public bool BooleanThree = false;
[DefaultValue(false)]
public bool BooleanThree { get; set; }

[Option("d", "double")]
public double NonBooleanValue = 0;
[DefaultValue(0)]
public double NonBooleanValue { get; set; }
}
}
#endif
Loading