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
63 changes: 63 additions & 0 deletions src/CommandLine/ParserResultExtensionsAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace CommandLine
{
public static partial class ParserResultExtensions
{
/// <summary>
/// Executes asynchronously <paramref name="action"/> if <see cref="CommandLine.ParserResult{T}"/> contains
/// parsed values.
/// </summary>
/// <typeparam name="T">Type of the target instance built with parsed value.</typeparam>
/// <param name="result">An <see cref="CommandLine.ParserResult{T}"/> instance.</param>
/// <param name="action">The <see cref="Func{T, Task}"/> to execute.</param>
/// <returns>The same <paramref name="result"/> instance as a <see cref="Task"/> instance.</returns>
public static async Task<ParserResult<T>> WithParsedAsync<T>(this ParserResult<T> result, Func<T, Task> action)
{
if (result is Parsed<T> parsed)
{
await action(parsed.Value);
}
return result;
}

/// <summary>
/// Executes asynchronously <paramref name="action"/> if parsed values are of <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">Type of the target instance built with parsed value.</typeparam>
/// <param name="result">An verb result instance.</param>
/// <param name="action">The <see cref="Func{T, Task}"/> to execute.</param>
/// <returns>The same <paramref name="result"/> instance as a <see cref="Task"/> instance.</returns>
public static async Task<ParserResult<object>> WithParsedAsync<T>(this ParserResult<object> result, Func<T, Task> action)
{
if (result is Parsed<object> parsed)
{
if (parsed.Value is T value)
{
await action(value);
}
}
return result;
}

/// <summary>
/// Executes asynchronously <paramref name="action"/> if <see cref="CommandLine.ParserResult{T}"/> lacks
/// parsed values and contains errors.
/// </summary>
/// <typeparam name="T">Type of the target instance built with parsed value.</typeparam>
/// <param name="result">An <see cref="CommandLine.ParserResult{T}"/> instance.</param>
/// <param name="action">The <see cref="System.Func{Task}"/> delegate to execute.</param>
/// <returns>The same <paramref name="result"/> instance as a <see cref="Task"/> instance.</returns>
public static async Task<ParserResult<T>> WithNotParsedAsync<T>(this ParserResult<T> result, Func<IEnumerable<Error>, Task> action)
{
if (result is NotParsed<T> notParsed)
{
await action(notParsed.Errors);
}
return result;
}
}
}
88 changes: 88 additions & 0 deletions tests/CommandLine.Tests/Unit/ParserResultExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using CommandLine.Tests.Fakes;
using Xunit;
using FluentAssertions;
using System.Threading.Tasks;

namespace CommandLine.Tests.Unit
{
Expand All @@ -21,6 +22,16 @@ public static void Invoke_parsed_lambda_when_parsed()
"value".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_parsed_lambda_when_parsedAsync()
{
var expected = string.Empty;
await Parser.Default.ParseArguments<Simple_Options>(new[] { "--stringvalue", "value" })
.WithParsedAsync(opts => Task.Run(() => expected = opts.StringValue));

"value".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Invoke_parsed_lambda_when_parsed_for_verbs()
{
Expand All @@ -34,6 +45,20 @@ public static void Invoke_parsed_lambda_when_parsed_for_verbs()
"https://value.org/user/file.git".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_parsed_lambda_when_parsed_for_verbsAsync()
{
var expected = string.Empty;
var parsedArguments = Parser.Default.ParseArguments<Add_Verb, Commit_Verb, Clone_Verb>(
new[] { "clone", "https://value.org/user/file.git" });

await parsedArguments.WithParsedAsync<Add_Verb>(opts => Task.Run(() => expected = "wrong1"));
await parsedArguments.WithParsedAsync<Commit_Verb>(opts => Task.Run(() => expected = "wrong2"));
await parsedArguments.WithParsedAsync<Clone_Verb>(opts => Task.Run(() => expected = opts.Urls.First()));

"https://value.org/user/file.git".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Invoke_not_parsed_lambda_when_not_parsed()
{
Expand All @@ -44,6 +69,16 @@ public static void Invoke_not_parsed_lambda_when_not_parsed()
"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_not_parsed_lambda_when_not_parsedAsync()
{
var expected = "a default";
await Parser.Default.ParseArguments<Simple_Options>(new[] { "-i", "aaa" })
.WithNotParsedAsync(_ => Task.Run(() => expected = "changed"));

"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Invoke_not_parsed_lambda_when_parsed_for_verbs()
{
Expand All @@ -57,6 +92,20 @@ public static void Invoke_not_parsed_lambda_when_parsed_for_verbs()
"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_not_parsed_lambda_when_parsed_for_verbsAsync()
{
var expected = "a default";
var parsedArguments = Parser.Default.ParseArguments<Add_Verb, Commit_Verb, Clone_Verb>(new[] { "undefined", "-xyz" });

await parsedArguments.WithParsedAsync<Add_Verb>(opts => Task.Run(() => expected = "wrong1"));
await parsedArguments.WithParsedAsync<Commit_Verb>(opts => Task.Run(() => expected = "wrong2"));
await parsedArguments.WithParsedAsync<Clone_Verb>(opts => Task.Run(() => expected = "wrong3"));
await parsedArguments.WithNotParsedAsync(_ => Task.Run(() => expected = "changed"));

"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Invoke_proper_lambda_when_parsed()
{
Expand All @@ -68,6 +117,18 @@ public static void Invoke_proper_lambda_when_parsed()
"value".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_proper_lambda_when_parsedAsync()
{
var expected = string.Empty;
var parsedArguments = Parser.Default.ParseArguments<Simple_Options>(new[] { "--stringvalue", "value" });

await parsedArguments.WithParsedAsync(opts => Task.Run(() => expected = opts.StringValue));
await parsedArguments.WithNotParsedAsync(_ => Task.Run(() => expected = "changed"));

"value".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Invoke_proper_lambda_when_not_parsed()
{
Expand All @@ -79,6 +140,18 @@ public static void Invoke_proper_lambda_when_not_parsed()
"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_proper_lambda_when_not_parsedAsync()
{
var expected = "a default";
var parsedArguments = Parser.Default.ParseArguments<Simple_Options>(new[] { "-i", "aaa" });

await parsedArguments.WithParsedAsync(opts => Task.Run(() => expected = opts.StringValue));
await parsedArguments.WithNotParsedAsync(_ => Task.Run(() => expected = "changed"));

"changed".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Turn_sucessful_parsing_into_exit_code()
{
Expand Down Expand Up @@ -139,6 +212,21 @@ public static void Invoke_parsed_lambda_when_parsed_for_base_verbs()
"dummy.bin".Should().BeEquivalentTo(expected);
}

[Fact]
public static async Task Invoke_parsed_lambda_when_parsed_for_base_verbsAsync()
{
var expected = string.Empty;
var parsedArguments = Parser.Default.ParseArguments<Add_Verb, Commit_Verb, Clone_Verb, Derived_Verb>(
new[] { "derivedadd", "dummy.bin" });

await parsedArguments.WithParsedAsync<Add_Verb>(opts => Task.Run(() => expected = "wrong1"));
await parsedArguments.WithParsedAsync<Commit_Verb>(opts => Task.Run(() => expected = "wrong2"));
await parsedArguments.WithParsedAsync<Clone_Verb>(opts => Task.Run(() => expected = "wrong3"));
await parsedArguments.WithParsedAsync<Base_Class_For_Verb>(opts => Task.Run(() => expected = opts.FileName));

"dummy.bin".Should().BeEquivalentTo(expected);
}

[Fact]
public static void Turn_sucessful_parsing_into_exit_code_for_single_base_verbs()
{
Expand Down