mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-04-25 12:42:51 +08:00
Added the ITypeResolver to the ExceptionHandler (#1411)
This commit is contained in:
parent
a94bc15746
commit
544e6a92df
docs/input/cli
src/Spectre.Console.Cli
test/Spectre.Console.Cli.Tests/Unit
@ -53,7 +53,11 @@ Using the `SetExceptionHandler()` during configuration it is possible to handle
|
|||||||
This method comes in two flavours: One that uses the default exitCode (or `return` value) of `-1` and one
|
This method comes in two flavours: One that uses the default exitCode (or `return` value) of `-1` and one
|
||||||
where the exitCode needs to be supplied.
|
where the exitCode needs to be supplied.
|
||||||
|
|
||||||
### Using `SetExceptionHandler(Func<Exception, int> handler)`
|
The `ITypeResolver?` parameter will be null, when the exception occurs while no `ITypeResolver` is available.
|
||||||
|
(Basically the `ITypeResolver` will be set, when the exception occurs during a command execution, but not
|
||||||
|
during the parsing phase and construction of the command.)
|
||||||
|
|
||||||
|
### Using `SetExceptionHandler(Func<Exception, ITypeResolver?, int> handler)`
|
||||||
|
|
||||||
Using this method exceptions can be handled in a custom way. The return value of the handler is used as
|
Using this method exceptions can be handled in a custom way. The return value of the handler is used as
|
||||||
the exitCode for the application.
|
the exitCode for the application.
|
||||||
@ -71,7 +75,7 @@ namespace MyApp
|
|||||||
|
|
||||||
app.Configure(config =>
|
app.Configure(config =>
|
||||||
{
|
{
|
||||||
config.SetExceptionHandler(ex =>
|
config.SetExceptionHandler((ex, resolver) =>
|
||||||
{
|
{
|
||||||
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
|
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
|
||||||
return -99;
|
return -99;
|
||||||
@ -84,9 +88,9 @@ namespace MyApp
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using `SetExceptionHandler(Action<Exception> handler)`
|
### Using `SetExceptionHandler(Action<Exception, ITypeResolver?> handler)`
|
||||||
|
|
||||||
Using this method exceptions can be handled in a custom way, much the same as with the `SetExceptionHandler(Func<Exception, int> handler)`.
|
Using this method exceptions can be handled in a custom way, much the same as with the `SetExceptionHandler(Func<Exception, ITypeResolver?, int> handler)`.
|
||||||
Using the `Action` as the handler however, it is not possible (or required) to supply a return value.
|
Using the `Action` as the handler however, it is not possible (or required) to supply a return value.
|
||||||
The exitCode for the application will be `-1`.
|
The exitCode for the application will be `-1`.
|
||||||
|
|
||||||
@ -103,7 +107,7 @@ namespace MyApp
|
|||||||
|
|
||||||
app.Configure(config =>
|
app.Configure(config =>
|
||||||
{
|
{
|
||||||
config.SetExceptionHandler(ex =>
|
config.SetExceptionHandler((ex, resolver) =>
|
||||||
{
|
{
|
||||||
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
|
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
|
||||||
});
|
});
|
||||||
|
@ -102,7 +102,7 @@ public sealed class CommandApp : ICommandApp
|
|||||||
|
|
||||||
if (_configurator.Settings.ExceptionHandler != null)
|
if (_configurator.Settings.ExceptionHandler != null)
|
||||||
{
|
{
|
||||||
return _configurator.Settings.ExceptionHandler(ex);
|
return _configurator.Settings.ExceptionHandler(ex, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the exception.
|
// Render the exception.
|
||||||
|
@ -367,11 +367,11 @@ public static class ConfiguratorExtensions
|
|||||||
/// <param name="configurator">The configurator.</param>
|
/// <param name="configurator">The configurator.</param>
|
||||||
/// <param name="exceptionHandler">The Action that handles the exception.</param>
|
/// <param name="exceptionHandler">The Action that handles the exception.</param>
|
||||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||||
public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Action<Exception> exceptionHandler)
|
public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Action<Exception, ITypeResolver?> exceptionHandler)
|
||||||
{
|
{
|
||||||
return configurator.SetExceptionHandler(ex =>
|
return configurator.SetExceptionHandler((ex, resolver) =>
|
||||||
{
|
{
|
||||||
exceptionHandler(ex);
|
exceptionHandler(ex, resolver);
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -382,7 +382,7 @@ public static class ConfiguratorExtensions
|
|||||||
/// <param name="configurator">The configurator.</param>
|
/// <param name="configurator">The configurator.</param>
|
||||||
/// <param name="exceptionHandler">The Action that handles the exception.</param>
|
/// <param name="exceptionHandler">The Action that handles the exception.</param>
|
||||||
/// <returns>A configurator that can be used to configure the application further.</returns>
|
/// <returns>A configurator that can be used to configure the application further.</returns>
|
||||||
public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Func<Exception, int>? exceptionHandler)
|
public static IConfigurator SetExceptionHandler(this IConfigurator configurator, Func<Exception, ITypeResolver?, int>? exceptionHandler)
|
||||||
{
|
{
|
||||||
if (configurator == null)
|
if (configurator == null)
|
||||||
{
|
{
|
||||||
|
@ -91,6 +91,8 @@ public interface ICommandAppSettings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a handler for Exceptions.
|
/// Gets or sets a handler for Exceptions.
|
||||||
/// <para>This handler will not be called, if <see cref="PropagateExceptions"/> is set to <c>true</c>.</para>
|
/// <para>This handler will not be called, if <see cref="PropagateExceptions"/> is set to <c>true</c>.</para>
|
||||||
|
/// The <see cref="ITypeResolver"/> argument will only be not-null, when the exception occurs during execution of
|
||||||
|
/// a command. I.e. only when the resolver is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<Exception, int>? ExceptionHandler { get; set; }
|
public Func<Exception, ITypeResolver?, int>? ExceptionHandler { get; set; }
|
||||||
}
|
}
|
@ -127,6 +127,8 @@ internal sealed class CommandExecutor
|
|||||||
CommandContext context,
|
CommandContext context,
|
||||||
ITypeResolver resolver,
|
ITypeResolver resolver,
|
||||||
IConfiguration configuration)
|
IConfiguration configuration)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// Bind the command tree against the settings.
|
// Bind the command tree against the settings.
|
||||||
var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver);
|
var settings = CommandBinder.Bind(tree, leaf.Command.SettingsType, resolver);
|
||||||
@ -161,4 +163,9 @@ internal sealed class CommandExecutor
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) when (configuration.Settings is { ExceptionHandler: not null, PropagateExceptions: false })
|
||||||
|
{
|
||||||
|
return configuration.Settings.ExceptionHandler(ex, resolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ internal sealed class CommandAppSettings : ICommandAppSettings
|
|||||||
public ParsingMode ParsingMode =>
|
public ParsingMode ParsingMode =>
|
||||||
StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed;
|
StrictParsing ? ParsingMode.Strict : ParsingMode.Relaxed;
|
||||||
|
|
||||||
public Func<Exception, int>? ExceptionHandler { get; set; }
|
public Func<Exception, ITypeResolver?, int>? ExceptionHandler { get; set; }
|
||||||
|
|
||||||
public CommandAppSettings(ITypeRegistrar registrar)
|
public CommandAppSettings(ITypeRegistrar registrar)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,7 @@ public sealed partial class CommandAppTests
|
|||||||
app.Configure(config =>
|
app.Configure(config =>
|
||||||
{
|
{
|
||||||
config.AddCommand<ThrowingCommand>("throw");
|
config.AddCommand<ThrowingCommand>("throw");
|
||||||
config.SetExceptionHandler(_ =>
|
config.SetExceptionHandler((_, _) =>
|
||||||
{
|
{
|
||||||
exceptionHandled = true;
|
exceptionHandled = true;
|
||||||
});
|
});
|
||||||
@ -74,7 +74,7 @@ public sealed partial class CommandAppTests
|
|||||||
app.Configure(config =>
|
app.Configure(config =>
|
||||||
{
|
{
|
||||||
config.AddCommand<ThrowingCommand>("throw");
|
config.AddCommand<ThrowingCommand>("throw");
|
||||||
config.SetExceptionHandler(_ =>
|
config.SetExceptionHandler((_, _) =>
|
||||||
{
|
{
|
||||||
exceptionHandled = true;
|
exceptionHandled = true;
|
||||||
return -99;
|
return -99;
|
||||||
@ -88,5 +88,49 @@ public sealed partial class CommandAppTests
|
|||||||
result.ExitCode.ShouldBe(-99);
|
result.ExitCode.ShouldBe(-99);
|
||||||
exceptionHandled.ShouldBeTrue();
|
exceptionHandled.ShouldBeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_Have_Resolver_Set_When_Exception_Occurs_In_Command_Execution()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
ITypeResolver resolver = null;
|
||||||
|
var app = new CommandAppTester();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.AddCommand<ThrowingCommand>("throw");
|
||||||
|
config.SetExceptionHandler((_, r) =>
|
||||||
|
{
|
||||||
|
resolver = r;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// When
|
||||||
|
app.Run(new[] { "throw" });
|
||||||
|
|
||||||
|
// Then
|
||||||
|
resolver.ShouldNotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_Not_Have_Resolver_Set_When_Exception_Occurs_Before_Command_Execution()
|
||||||
|
{
|
||||||
|
// Given
|
||||||
|
ITypeResolver resolver = null;
|
||||||
|
var app = new CommandAppTester();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.AddCommand<DogCommand>("Лайка");
|
||||||
|
config.SetExceptionHandler((_, r) =>
|
||||||
|
{
|
||||||
|
resolver = r;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// When
|
||||||
|
app.Run(new[] { "throw", "on", "arg", "parsing" });
|
||||||
|
|
||||||
|
// Then
|
||||||
|
resolver.ShouldBeNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user