mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Unwrap TargetInvocationException to provide more user-friendly errors when binding fails
This commit is contained in:
@@ -946,5 +946,48 @@ public class Command : ICommand
|
||||
exitCode.Should().NotBe(0);
|
||||
stdErr.Should().Contain("Hello world");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Parameter_or_option_value_conversion_fails_if_the_static_parse_method_throws()
|
||||
{
|
||||
// Arrange
|
||||
var commandType = DynamicCommandBuilder.Compile(
|
||||
// language=cs
|
||||
@"
|
||||
public class CustomType
|
||||
{
|
||||
public string Value { get; }
|
||||
|
||||
private CustomType(string value) => Value = value;
|
||||
|
||||
public static CustomType Parse(string value) => throw new Exception(""Hello world"");
|
||||
}
|
||||
|
||||
[Command]
|
||||
public class Command : ICommand
|
||||
{
|
||||
[CommandOption('f')]
|
||||
public CustomType Foo { get; set; }
|
||||
|
||||
public ValueTask ExecuteAsync(IConsole console) => default;
|
||||
}
|
||||
");
|
||||
var application = new CliApplicationBuilder()
|
||||
.AddCommand(commandType)
|
||||
.UseConsole(FakeConsole)
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var exitCode = await application.RunAsync(
|
||||
new[] {"-f", "bar"},
|
||||
new Dictionary<string, string>()
|
||||
);
|
||||
|
||||
var stdErr = FakeConsole.ReadErrorString();
|
||||
|
||||
// Assert
|
||||
exitCode.Should().NotBe(0);
|
||||
stdErr.Should().Contain("Hello world");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Extensibility;
|
||||
using CliFx.Infrastructure;
|
||||
@@ -161,12 +162,18 @@ namespace CliFx
|
||||
}
|
||||
catch (Exception ex) when (ex is not CliFxException) // don't wrap CliFxException
|
||||
{
|
||||
// We use reflection-based invocation which can throw TargetInvocationException.
|
||||
// Unwrap these exceptions to provide a more user-friendly error message.
|
||||
var errorMessage = ex is TargetInvocationException invokeEx
|
||||
? invokeEx.InnerException?.Message ?? invokeEx.Message
|
||||
: ex.Message;
|
||||
|
||||
throw CliFxException.UserError(
|
||||
$"{memberSchema.GetKind()} {memberSchema.GetFormattedIdentifier()} cannot be set from provided argument(s):" +
|
||||
Environment.NewLine +
|
||||
rawValues.Select(v => '<' + v + '>').JoinToString(" ") +
|
||||
Environment.NewLine +
|
||||
$"Error: {ex.Message}",
|
||||
$"Error: {errorMessage}",
|
||||
ex
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user