Skip to content

Commit a7814e7

Browse files
committed
ValueParsers are now inherited in subcommands
Before this commit, sub commands did not inherit the value parsers. This is frustrating because we would need to add custom value parsers for every sub command. In the general case, it is optimal that one set of value parsers are used for all argument parsing in the application.
1 parent 9594670 commit a7814e7

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

src/CommandLineUtils/CommandLineApplication.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ internal CommandLineApplication(CommandLineApplication parent,
9393
ValidationErrorHandler = DefaultValidationErrorHandler;
9494
SetContext(context);
9595
_services = new Lazy<IServiceProvider>(() => new ServiceProvider(this));
96-
ValueParsers = new ValueParserProvider();
96+
ValueParsers = parent?.ValueParsers ?? new ValueParserProvider();
9797

9898
_conventionContext = CreateConventionContext();
9999

test/CommandLineUtils.Tests/ValueParserProviderCustomTests.cs

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
// Copyright (c) Nate McMaster.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using McMaster.Extensions.CommandLineUtils.Abstractions;
45
using System;
56
using System.Globalization;
6-
using System.Collections.Generic;
7+
using System.Threading.Tasks;
78
using Xunit;
8-
using McMaster.Extensions.CommandLineUtils.Abstractions;
99

1010
namespace McMaster.Extensions.CommandLineUtils.Tests
1111
{
12-
using System.Linq;
13-
1412
public class ValueParserProviderCustomTests
1513
{
1614

@@ -193,6 +191,75 @@ public void CustomParsersAreAutomaticallySingleValues()
193191
optionMapper.GetOptionType(typeof(double), app.ValueParsers));
194192
}
195193

194+
195+
[Command()]
196+
[Subcommand("subcommand", typeof(CustomParserProgramAttributesSubCommand))]
197+
private class CustomParserProgramAttributes
198+
{
199+
[Option("-a")]
200+
public DateTimeOffset MainDate { get; }
201+
}
202+
203+
[Command()]
204+
private class CustomParserProgramAttributesSubCommand
205+
{
206+
[Option("-b")]
207+
public DateTimeOffset SubDate { get; }
208+
209+
public Task<int> OnExecute(CommandLineApplication app)
210+
{
211+
return Task.FromResult(1);
212+
}
213+
}
214+
215+
[Fact]
216+
public void CustomParsersAreAvailableToSubCommands()
217+
{
218+
var expectedDate = new DateTimeOffset(2018, 02, 16, 21, 30, 33, 45, TimeSpan.FromHours(10));
219+
220+
221+
var app = new CommandLineApplication<CustomParserProgramAttributes>();
222+
app.ValueParsers.AddOrReplace(new MyDateTimeOffsetParser());
223+
app.Conventions.UseDefaultConventions();
224+
225+
var args = new[] { "-a", expectedDate.ToString("O"), "subcommand", "-b", expectedDate.AddSeconds(123456).ToString("O") };
226+
227+
var result = app.Execute(args);
228+
229+
Assert.Equal(1, result);
230+
Assert.Equal(expectedDate, app.Model.MainDate);
231+
Assert.Equal(expectedDate.AddSeconds(123456), ((CommandLineApplication<CustomParserProgramAttributesSubCommand>)app.Commands[0]).Model.SubDate);
232+
}
233+
234+
[Fact]
235+
public void CustomParsersAreAvailableToBuilderSubCommands()
236+
{
237+
var expectedDate = new DateTimeOffset(2018, 02, 16, 21, 30, 33, 45, TimeSpan.FromHours(10));
238+
DateTimeOffset actualMainDate = default;
239+
DateTimeOffset actualSubDate = default;
240+
241+
var app = new CommandLineApplication();
242+
app.ValueParsers.AddOrReplace(new MyDateTimeOffsetParser());
243+
244+
var mainDate = app.Option<DateTimeOffset>("-a", "The main date to parse", CommandOptionType.SingleValue);
245+
app.Command("subcommand", configCmd =>
246+
{
247+
var subDate = configCmd.Option<DateTimeOffset>("-b", "A date for the sub command", CommandOptionType.SingleValue);
248+
249+
configCmd.OnExecute(() =>
250+
{
251+
actualMainDate = mainDate.ParsedValue;
252+
actualSubDate = subDate.ParsedValue;
253+
});
254+
});
255+
256+
var args = new[] { "-a", expectedDate.ToString("O"), "subcommand", "-b", expectedDate.AddSeconds(123456).ToString("O") };
257+
app.Execute(args);
258+
259+
Assert.Equal(expectedDate, actualMainDate);
260+
Assert.Equal(expectedDate.AddSeconds(123456), actualSubDate);
261+
}
262+
196263
private class BadValueParser : IValueParser
197264
{
198265
public Type TargetType { get; } = null;

0 commit comments

Comments
 (0)