Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Saalvage committed Jun 19, 2022
1 parent b0b0ec9 commit ce9cfc4
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
9 changes: 7 additions & 2 deletions src/CommandLine/Core/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ static class ReflectionExtensions
{
public static IEnumerable<T> GetSpecifications<T>(this Type type, Func<PropertyInfo, T> selector)
{
return from pi in type.FlattenHierarchy().SelectMany(x => x.GetTypeInfo().GetProperties())
return from pi in type.FlattenHierarchy()
.SelectMany(x => x.GetTypeInfo()
.GetProperties(BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public))
let attrs = pi.GetCustomAttributes(true)
where
attrs.OfType<OptionAttribute>().Any() ||
Expand All @@ -38,7 +41,9 @@ public static Maybe<VerbAttribute> GetVerbSpecification(this Type type)
public static Maybe<Tuple<PropertyInfo, UsageAttribute>> GetUsageData(this Type type)
{
return
(from pi in type.FlattenHierarchy().SelectMany(x => x.GetTypeInfo().GetProperties())
(from pi in type.FlattenHierarchy().SelectMany(x => x.GetTypeInfo().GetProperties(
BindingFlags.Instance | BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.Public))
let attrs = pi.GetCustomAttributes(typeof(UsageAttribute), true)
where attrs.Any()
select Tuple.Create(pi, (UsageAttribute)attrs.First()))
Expand Down
6 changes: 4 additions & 2 deletions src/CommandLine/Text/HelpText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -839,8 +839,10 @@ private IEnumerable<Specification> GetSpecificationsFromType(Type type)
var prop = tuple.Item1;
var attr = tuple.Item2;
var examples = (IEnumerable<Example>)prop
.GetValue(null, BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty, null, null, null);
var examples = (IEnumerable<Example>) prop
.GetValue(null,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static |
BindingFlags.GetProperty, null, null, null);
return Tuple.Create(attr, examples);
});
Expand Down
65 changes: 65 additions & 0 deletions tests/CommandLine.Tests/Unit/Issue830Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.IO;
using CommandLine.Text;
using FluentAssertions;
using Xunit;

// Issue #830
// Allow private properties as options and usage
namespace CommandLine.Tests.Unit
{
public class Issue830Tests
{
[Fact]
public void Parse_options_with_private_value_and_option()
{
var expectedOptions = new Options
{
Option = "a",
Value = "b"
};

var result = Parser.Default.ParseArguments<Options>(
new[] { "b", "--opt", "a" });

((Parsed<Options>)result).Value.Should().BeEquivalentTo(expectedOptions);
}

[Fact]
public void Print_private_usage()
{
var help = new StringWriter();
var sut = new Parser(config => config.HelpWriter = help);

sut.ParseArguments<Options>(new string[] { "--help" });
var result = help.ToString();

var lines = result.ToLines().TrimStringArray();
lines[3].Should().BeEquivalentTo("Do something very cool:");
lines[4].Should().BeEquivalentTo("CommandLine --opt test1 test2");
}

private class Options
{
public string Option { get => PrivateOption; set => PrivateOption = value; }

public string Value { get => PrivateValue; set => PrivateValue = value; }

[Option("opt", Required = true)]
private string PrivateOption { get; set; }

[Value(0, Required = true)]
private string PrivateValue { get; set; }

[Usage]
private static IEnumerable<Example> PrivateUsage { get; } = new List<Example>
{
new Example("Do something very cool", new Options
{
PrivateOption = "test1",
PrivateValue = "test2"
})
};
}
}
}

0 comments on commit ce9cfc4

Please sign in to comment.