mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	Merge pull request #1141 from 0xced/better-conversion-errors
This commit is contained in:
		| @@ -42,6 +42,13 @@ public class CommandRuntimeException : CommandAppException | ||||
|         return new CommandRuntimeException($"Could not find converter for type '{parameter.ParameterType.FullName}'."); | ||||
|     } | ||||
|  | ||||
|     internal static CommandRuntimeException ConversionFailed(MappedCommandParameter parameter, TypeConverter typeConverter, Exception exception) | ||||
|     { | ||||
|         var standardValues = typeConverter.GetStandardValuesSupported() ? typeConverter.GetStandardValues() : null; | ||||
|         var validValues = standardValues == null ? string.Empty : $" Valid values are '{string.Join("', '", standardValues.Cast<object>().Select(Convert.ToString))}'"; | ||||
|         return new CommandRuntimeException($"Failed to convert '{parameter.Value}' to {parameter.Parameter.ParameterType.Name}.{validValues}", exception); | ||||
|     } | ||||
|  | ||||
|     internal static CommandRuntimeException ValidationFailed(ValidationResult result) | ||||
|     { | ||||
|         return new CommandRuntimeException(result.Message ?? "Unknown validation error."); | ||||
|   | ||||
| @@ -84,8 +84,18 @@ internal static class CommandValueResolver | ||||
|                             throw CommandRuntimeException.NoConverterFound(mapped.Parameter); | ||||
|                         } | ||||
|  | ||||
|                         object? value; | ||||
|                         try | ||||
|                         { | ||||
|                             value = converter.ConvertFromInvariantString(mapped.Value ?? string.Empty); | ||||
|                         } | ||||
|                         catch (Exception exception) | ||||
|                         { | ||||
|                             throw CommandRuntimeException.ConversionFailed(mapped, converter, exception); | ||||
|                         } | ||||
|  | ||||
|                         // Assign the value to the parameter. | ||||
|                         binder.Bind(mapped.Parameter, resolver, converter.ConvertFromInvariantString(mapped.Value ?? string.Empty)); | ||||
|                         binder.Bind(mapped.Parameter, resolver, value); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| [Description("The horse command.")] | ||||
| public class HorseCommand : AnimalCommand<MammalSettings> | ||||
| public class HorseCommand : AnimalCommand<HorseSettings> | ||||
| { | ||||
|     public override int Execute(CommandContext context, MammalSettings settings) | ||||
|     public override int Execute(CommandContext context, HorseSettings settings) | ||||
|     { | ||||
|         DumpSettings(context, settings); | ||||
|         return 0; | ||||
|   | ||||
| @@ -0,0 +1,7 @@ | ||||
| namespace Spectre.Console.Tests.Data; | ||||
|  | ||||
| public class HorseSettings : MammalSettings | ||||
| { | ||||
|     [CommandOption("-d|--day")] | ||||
|     public DayOfWeek Day { get; set; } | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Model> | ||||
|   <!--ANIMAL--> | ||||
|   <Command Name="animal" IsBranch="true" Settings="Spectre.Console.Tests.Data.AnimalSettings"> | ||||
| @@ -27,9 +27,9 @@ | ||||
|         </Parameters> | ||||
|       </Command> | ||||
|       <!--HORSE--> | ||||
|       <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings"> | ||||
|       <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.HorseSettings"> | ||||
|         <Parameters> | ||||
|           <Option Shadowed="true" Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" /> | ||||
|           <Option Short="d" Long="day" Value="NULL" Required="false" Kind="scalar" ClrType="System.DayOfWeek" /> | ||||
|         </Parameters> | ||||
|       </Command> | ||||
|     </Command> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Model> | ||||
|   <!--ANIMAL--> | ||||
|   <Command Name="animal" IsBranch="true" Settings="Spectre.Console.Tests.Data.AnimalSettings"> | ||||
| @@ -23,8 +23,9 @@ | ||||
|       </Parameters> | ||||
|     </Command> | ||||
|     <!--HORSE--> | ||||
|     <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings"> | ||||
|     <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.HorseSettings"> | ||||
|       <Parameters> | ||||
|         <Option Short="d" Long="day" Value="NULL" Required="false" Kind="scalar" ClrType="System.DayOfWeek" /> | ||||
|         <Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" /> | ||||
|       </Parameters> | ||||
|     </Command> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Model> | ||||
|   <!--DEFAULT COMMAND--> | ||||
|   <Command Name="__default_command" IsBranch="false" IsDefault="true" ClrType="Spectre.Console.Tests.Data.DogCommand" Settings="Spectre.Console.Tests.Data.DogSettings"> | ||||
| @@ -19,7 +19,7 @@ | ||||
|     </Parameters> | ||||
|   </Command> | ||||
|   <!--HORSE--> | ||||
|   <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.MammalSettings"> | ||||
|   <Command Name="horse" IsBranch="false" ClrType="Spectre.Console.Tests.Data.HorseCommand" Settings="Spectre.Console.Tests.Data.HorseSettings"> | ||||
|     <Parameters> | ||||
|       <Argument Name="LEGS" Position="0" Required="false" Kind="scalar" ClrType="System.Int32"> | ||||
|         <Description>The number of legs.</Description> | ||||
| @@ -31,6 +31,7 @@ | ||||
|       <Option Short="a" Long="alive,not-dead" Value="NULL" Required="false" Kind="flag" ClrType="System.Boolean"> | ||||
|         <Description>Indicates whether or not the animal is alive.</Description> | ||||
|       </Option> | ||||
|       <Option Short="d" Long="day" Value="NULL" Required="false" Kind="scalar" ClrType="System.DayOfWeek" /> | ||||
|       <Option Short="n,p" Long="name,pet-name" Value="VALUE" Required="false" Kind="scalar" ClrType="System.String" /> | ||||
|     </Parameters> | ||||
|   </Command> | ||||
|   | ||||
| @@ -29,5 +29,52 @@ public sealed partial class CommandAppTests | ||||
|                 cat.Agility.ShouldBe(6); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_Convert_Enum_Ignoring_Case() | ||||
|         { | ||||
|             // Given | ||||
|             var app = new CommandAppTester(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.AddCommand<HorseCommand>("horse"); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = app.Run(new[] { "horse", "--day", "friday" }); | ||||
|  | ||||
|             // Then | ||||
|             result.ExitCode.ShouldBe(0); | ||||
|             result.Settings.ShouldBeOfType<HorseSettings>().And(horse => | ||||
|             { | ||||
|                 horse.Day.ShouldBe(DayOfWeek.Friday); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void Should_List_All_Valid_Enum_Values_On_Conversion_Error() | ||||
|         { | ||||
|             // Given | ||||
|             var app = new CommandAppTester(); | ||||
|             app.Configure(config => | ||||
|             { | ||||
|                 config.AddCommand<HorseCommand>("horse"); | ||||
|             }); | ||||
|  | ||||
|             // When | ||||
|             var result = app.Run(new[] { "horse", "--day", "heimday" }); | ||||
|  | ||||
|             // Then | ||||
|             result.ExitCode.ShouldBe(-1); | ||||
|             result.Output.ShouldStartWith("Error"); | ||||
|             result.Output.ShouldContain("heimday"); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Sunday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Monday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Tuesday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Wednesday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Thursday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Friday)); | ||||
|             result.Output.ShouldContain(nameof(DayOfWeek.Saturday)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Patrik Svensson
					Patrik Svensson